设计模式-组合模式

设计模式-组合模式

一、定义

定义:将对象组合成树形结构以表示“部分-整体”

组合模式使客户端对单个对象和组合对象保持一致的处理

类型:结构型

二、适用场景

希望客户端可以忽略组合对象与单个对象的差异时

处理一个树形结构时

三、优点

清楚地定义分层次的复杂对象,表示对象的全部或者部分层次

让客户端忽略了层次的差异,方便对整个层次结构进行控制。

简化客户端的代码

符合开闭原则

四、缺点

限制类型时会较为复杂

使设计变得更加抽象

五、Coding(场景课程目录,课程。课程目录里可以有多个课程,或者课程目录有多个目录)

1. 创建CatalogComponent 抽象类

/**
 * 目录组件
 */
public abstract class CatalogComponent {
    public void add(CatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持添加操作");
    }

    public void remove(CatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持删除操作");
    }

    public String getName(CatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持获取名称操作");
    }

    public double getNPrice(CatalogComponent catalogComponent){
        throw new UnsupportedOperationException("不支持获取价格操作");
    }

    public void print(){
        throw new UnsupportedOperationException("不支持打印操作");
    }
}

  

2. 创建Course课程类,继承课程目录。课程类中有name和price属性,以及重写getName方法,getPrice方法,和print方法

public class Course extends  CatalogComponent {
    private String name;
    private double price;

    public Course(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String getName(CatalogComponent catalogComponent) {
        return this.name;
    }

    @Override
    public double getNPrice(CatalogComponent catalogComponent) {
        return this.price;
    }

    @Override
    public void print() {
        System.out.println("课程名称:" + name + " 价格: " + price);
    }
}

  

3. 创建CourseCatalog 类。里面有多个课程目录。level代码目录等级。

/**
 * 课程目录
 */
public class CourseCatalog  extends  CatalogComponent{
    private List<CatalogComponent> items = new ArrayList<>();

    //目录名称
    private String name;

    private Integer level;

    public CourseCatalog(String name, Integer level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public String getName(CatalogComponent catalogComponent) {
        return this.name;
    }

    @Override
    public void add(CatalogComponent catalogComponent) {
       items.add(catalogComponent);
    }

    @Override
    public void remove(CatalogComponent catalogComponent) {
        items.remove(catalogComponent);
    }

    @Override
    public void print() {
        System.out.println(this.name);
        for(CatalogComponent catalogComponent : items){
            if(this.level != null){
                for(int i = 0; i < this.level ; i++){
                    System.out.print("  ");
                }
            }

            catalogComponent.print();
        }

    }
}

  

4. 测试

public class Test {
    public static void main(String[] args) {

        CatalogComponent javaScriptCourse = new Course("JavaScript基础",400);
        CatalogComponent typeScriptCourse = new Course("TypeScript基础",300);
        CatalogComponent javaCourse = new Course("Java基础",200);
        CatalogComponent javaCourse2 = new Course("Java设计模式",200);
        CatalogComponent javaCourse3 = new Course("Android课程",300);

        CatalogComponent javaCourseCatalog = new CourseCatalog("Java课程目录", 2);

        javaCourseCatalog.add(javaCourse);
        javaCourseCatalog.add(javaCourse2);
        javaCourseCatalog.add(javaCourse3);

        CatalogComponent mainCourseCatalog = new CourseCatalog("课程主目录", 1);
        mainCourseCatalog.add(javaScriptCourse);
        mainCourseCatalog.add(typeScriptCourse);
        mainCourseCatalog.add(javaCourseCatalog);
        mainCourseCatalog.print();
    }
}

  输出为:

设计模式-组合模式

5 UML图

设计模式-组合模式

六、在源码中的应用

1.jdk java.awt中的Container类

设计模式-组合模式

add方法

    public Component add(Component var1) {
        this.addImpl(var1, (Object)null, -1);
        return var1;
    }

  

2. HashMap

HasMap实现了Map接口,并且putAll测参数为Map

public void putAll(Map<? extends K, ? extends V> var1) 

3. Java.util.ArrayList

ArrayList实现List接口,List接口继承自Collection,addAll中参数为Collection

public boolean addAll(Collection<? extends E> var1) 

4. Mybatis中SqlNode 接口

public interface SqlNode {
    boolean apply(DynamicContext var1);
}  

多个SqlNode对象

public class MixedSqlNode implements SqlNode {
    private List<SqlNode> contents;

    public MixedSqlNode(List<SqlNode> contents) {
        this.contents = contents;
    }

    public boolean apply(DynamicContext context) {
        Iterator i$ = this.contents.iterator();

        while(i$.hasNext()) {
            SqlNode sqlNode = (SqlNode)i$.next();
            sqlNode.apply(context);
        }

        return true;
    }
}