组合模式篇章一

思考组合模式

1 组合模式的本质
	组合模式的本质: 统一叶子对象和组合对象.
  组合模式通过把叶子对象当成特殊的组合对象看待,从而对叶子对象和组合对象一视同仁,
  全部当成了Component对象,有机的统一了叶子对象和组合对象.
2 何时选用组合模式
①如果你想表示对象的部分-整体层次结构,可以选用组合模式
②如果你希望统一的使用组合结构中的所有对象,可以选用组合模式,这正是组合模式提供的主要功能.

相关模式(后面会写案例)

1 组合模式和装饰模式
2 组合模式和享元模式
3 组合模式和迭代器模式
4 组合模式和访问者模式
5 组合模式和职责链模式
6 组合模式和命令模式

实践案例

组合模式示例代码

1: UML类图结构
image
2: 组合模式角色组成
(个人理解)
抽象组件类
组合组件类
叶子组件类
3: 组合模式角色关系
抽象组件和组合组件类: 继承 + 组合(由这个组合可以组装成责任链的处理链)
抽象组件和叶子组件类: 继承

4: 案例代码

public abstract class Component {
/*
1: 定义操作
2: 还是定义操作
*/
public abstract void someOperation();

public void addChild(Component component) {
    // 缺省的实现,抛出例外,因为叶子对象没有这个功能,或者子组件没有实现这个功能
    throw new UnsupportedOperationException("对象不支持这个功能");
}

public void removeChild(Component component) {
    throw new UnsupportedOperationException("对象不支持这个功能");
}

public Component getChildren(int index) {
    throw new UnsupportedOperationException("对象不支持这个功能");
}

}

public class Composite extends Component {

/**
 * 用来存储组合对象中包含的子组件对象
 */
private List<Component> childComponents = null;

@Override
public void someOperation() {
    if (childComponents != null && childComponents.size() > 0) {
        this.childComponents.forEach(c -> c.someOperation());
    }
}

@Override
public void addChild(Component component) {

// if (this.childComponents != null) {
// this.childComponents.add(component);
// }
//延迟初始化
if (childComponents == null) {
childComponents = new ArrayList();
}
childComponents.add(component);
}

@Override
public void removeChild(Component component) {
    if (this.childComponents != null) {
        this.childComponents.remove(component);
    }
}

/**
 *
 * @param index
 * @return
 */
@Override
public Component getChildren(int index) {
    if (childComponents != null){
        if(index>=0 && index<childComponents.size()){
            return childComponents.get(index);
        }
    }
    return null;
};

}

public class Leaf extends Component {
/**
*
*/
@Override
public void someOperation() {
//todo
}
}

public class Client2 {

public static void main(String[] args) {
    //定义多个Composite对象
    Component root = new Composite();
    Component c1 = new Composite();
    Component c2 = new Composite();
    //定义多个叶子对象
    Component leaf1 = new Leaf();
    Component leaf2 = new Leaf();
    Component leaf3 = new Leaf();

    //组和成为树形的对象结构
    root.addChild(c1);
    root.addChild(c2);
    root.addChild(leaf1);

    c1.addChild(leaf2);
    c2.addChild(leaf3);

    //操作Component对象
    Component children = root.getChildren(1);
    System.out.println(children);
}

}
运行结果:
可以参考树结构.
5: 安全性和透明性
本质就是客户使用的时候是否会发生误操作的情况,如果会发生误操作,就是透明性,如果不会
发生误操作,就是安全性.

组合模式结构树代码

public abstract class Component5 {

/**
 * 记录 父组件对象
 */
private Component5 parent = null;

/**
 * 获取一个组件的父组件对象
 * @return 一个组件的父组件对象
 */
public Component5 getParent() {
    return this.parent;
}

/**
 *
 * @param parent
 */
public void setParent(Component5 parent) {
    this.parent = parent;
}

/**
 * 返回某个组件的子组件对象
 * @return 某个组件的子组件对象
 */
public List<Component5> getChildren() {
    throw new UnsupportedOperationException("对象不支持这个功能");
}

/-------------------以下是原有的定义----------------------/

/**
 * 输出组件自身的名称
 */
public abstract void printStruct(String preStr);

/**
 * 向组合对象中加入组件对象
 * @param child 被加入组合对象中的组件对象
 */
public void addChild(Component5 child) {
    // 缺省的实现,抛出例外,因为叶子对象没有这个功能,或者子组件没有实现这个功能
    throw new UnsupportedOperationException("对象不支持这个功能");
}

/**
 * 从组合对象中移出某个组件对象
 * @param child 被移出的组件对象
 */
public void removeChild(Component5 child) {
    // 缺省的实现,抛出例外,因为叶子对象没有这个功能,或者子组件没有实现这个功能
    throw new UnsupportedOperationException("对象不支持这个功能");
}

/**
 * 返回某个索引对应的组件对象
 * @param index 需要获取的组件对象的索引,索引从0开始
 * @return 索引对应的组件对象
 */
public Component5 getChildren(int index) {
    throw new UnsupportedOperationException("对象不支持这个功能");
}

}

public class Composite5 extends Component5 {

/**
 * 用来存储组合对象中包含的子组件对象
 */
private List<Component5> childComponents = null;

private String name = "";

public Composite5(String name) {
    this.name = name;
}

/**
 *
 * @param preStr
 */
@Override
public void printStruct(String preStr) {
    //先把自己输出去
    System.out.println(preStr+"+"+this.name);
    //如果还包含有子组件,那么就输出这些子组件对象
    if(this.childComponents!=null){
        //然后添加一个空格,表示向后缩进一个空格
        preStr+=" ";
        //输出当前对象的子对象了
        for(Component5 c : childComponents){
            //递归输出每个子对象
            c.printStruct(preStr);
        }
    }
}

/**
 * 新增
 * @param child
 */
public void addChild(Component5 child) {
    //延迟初始化
    if (this.childComponents == null) {
        this.childComponents = new ArrayList<>();
    }

    this.childComponents.add(child);

    //添加对父组件的引用
    child.setParent(this);
}

/**
 * 其实就是将 : child 的 子组件都加到当前实例的 子组件当中
 * @param child 被移出的组件对象
 */
@Override
public void removeChild(Component5 child) {
    if (this.childComponents != null) {
        //查找到要删除的组件在集合中的索引位置
        int idx = this.childComponents.indexOf(child);
        if (idx != -1) {
            //先把被删除的商品类别对象的父商品类别,
            // 设置成为被删除的商品类别的子类别的父商品类别
            for (Component5 c : child.getChildren()) {
                ////删除的组件对象是本实例的一个子组件对象
                c.setParent(this);
                //把被删除的商品类别对象的子组件对象添加到当前实例中
                this.childComponents.add(c);
            }
            //真的删除
            this.childComponents.remove(child);
        }
    }
}

/**
 *
 * @return
 */
@Override
public List<Component5> getChildren() {
    return this.childComponents;
}

}

public class Leaf5 extends Component5 {

/**
 * 叶子对象的名字
 */
private String name = "";
/**
 * 构造方法,传入叶子对象的名字
 * @param name 叶子对象的名字
 */
public Leaf5(String name){
    this.name = name;
}

/**
 * 输出叶子对象的结构,叶子对象没有子对象,也就是输出叶子对象的名字
 * @param preStr 前缀,主要是按照层级拼接的空格,实现向后缩进
 */
@Override
public void printStruct(String preStr) {
    System.out.println(preStr+"-"+name);
}

}

public class Client5 {

public static void main(String[] args) {

    //定义所有的组合对象
    Component5 root = new Composite5("服装");
    Component5 c1 = new Composite5("男装");
    Component5 c2 = new Composite5("女装");
    //定义所有的叶子对象
    Component5 leaf1 = new Leaf5("衬衣");
    Component5 leaf2 = new Leaf5("夹克");
    Component5 leaf3 = new Leaf5("裙子");
    Component5 leaf4 = new Leaf5("套装");
    //按照树的结构来组合组合对象和叶子对象

    root.addChild(c1);
    root.addChild(c2);
    c1.addChild(leaf1);
    c1.addChild(leaf2);
    c2.addChild(leaf3);
    c2.addChild(leaf4);

    //调用根对象的输出功能来输出整棵树
    root.printStruct("");

    System.out.println("---------------------------->");

    //然后删除一个节点
    root.removeChild(c1);
    //重新输出整棵树
    root.printStruct("");

}

}


运行结果:
+服装
+男装
-衬衣
-夹克
+女装
-裙子
-套装
---------------------------->
+服装
+女装
-裙子
-套装
-衬衣
-夹克

组合模式和责任链模式组合应用代码

1: 寻找两种模式的共同点,然后从结构上进行构造.
组合模式:
image

职责链模式:
image

2: 上述共同点
①都是定义了抽象类,并定义了自己的处理方法
②子类和父类都存在的关系是继承
可以参考:
https://blog.csdn.net/liuchang840302/article/details/9107399
image

贴出代码:
public interface Filter {
String doFilter(String str);
}

public class Filter1 implements Filter {
@Override
public String doFilter(String str) {
str += "Filter1,";
return str;
}
}

public class Filter2 implements Filter {
@Override
public String doFilter(String str) {
str += "Filter2,";
return str;
}
}

public class Filter3 implements Filter {
@Override
public String doFilter(String str) {
str += "Filter3,";
return str;
}
}

public class Filter4 implements Filter {
@Override
public String doFilter(String str) {
str += "Filter4,";
return str;
}
}

public class Filter5 implements Filter {
@Override
public String doFilter(String str) {
str += "Filter5,";
return str;
}
}

public class FilterChain implements Filter {

//这个就是组合模式的结构
List<Filter> filters = null;

//构造list
public FilterChain addFilter(Filter filter) {
    //延迟初始化
    if (filters == null) {
        filters = new ArrayList<>();
    }
    filters.add(filter);
    return this;
}

/**
 *
 * @param str
 * @return
 */
@Override
public String doFilter(String str) {
    if (filters == null || filters.size() == 0) {
        return "处理链为空!";
    }
    for (Filter filter : filters) {
        str = filter.doFilter(str);
    }
    return str;
}

}

职责链处理结果:
123,mxm,456,Filter1,Filter2,Filter5,Filter3,Filter4,

代码还需要优化!

posted @ 2021-04-22 10:09  oldsmile  阅读(100)  评论(0)    收藏  举报