一天一种设计模式之八-----组合模式

一.组合模式简介

  1. 组合模式属于结构型模式

  2. 将组合模式合成树形结构以表示“部分-整体” 的层次结构。“Composite”使得用户对单个对象和组合对象的使用具有一致性。

  3. 适用性:

    1. 你想表示对象的部分-整体层次结构。

    2. 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

  4. 结构:

    1. Component 为组合中的对象声明接口。在适当情况下,实现所有类共有接口的缺省行为。声明一个接口用于访问和管理component的子组件。

    2. leaf 在组合中表示叶节点对象,叶节点没有子节点。

    3. composite 定义有子部件的那些不见的行为。存储子部件。在component接口中实现与子部件有关的操作。

    4. client接口操作组合不见的对象。

  5. 组合模式分为透明模式和安全模式

    1. 透明模式:在Component中声明所有用来管 理子对象的方法,如Add()方法,Remove()方法及GetChild()方法,所有实现Component接口的子类都具备这些方法,这使得 Component和子类具备一致的行为接口,使得对客户端无需区别树叶和树枝对象。

    2. 安全模式: 在透明模式基础上把Component中声明所有用来管理子对象的方法移到Composite中,在Composite实现子对象的管理方法,那么 Leaf就没有子对象管理方法,这使得Composite和Leaf的行为接口不一致,所以客户端在调用时要知道树叶和树枝对象存在。

  6. 组合模式符合开放封闭原则,迪米特法则。

  7. 组合模式优点

    1. 高层模块调用简单:一棵属性结构中所有节点都是component,局部和整体对调用者来说没有任何区别,也就是说,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。

    2. 节点自由增加:使用组合模式后,如果想增加一个树枝节点,树叶节点,只要找到它的父节点set进去就可以。对以后维护非常简单。

  8. 组合模式缺点

    1. 树枝和树叶的实现中直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。

    2. 通过继承来实现的结构型模式,一定要小心子类覆盖父类方法,因为这样可能导致整个结构的功能发生难以预知的变化。

  9. 应用场景:

    1. 维护一个树形菜单,文件系统等。

二.测试代码

1.下述代码是一种透明模式的组合模式

public class ZuhemoshiTest {
    public static void main(String[] args) {
        Employer employer=new ProjectManager("项目经理");
        Employer employer2=new Programer("程序员1");
        Employer employer3=new Programer("程序员2");
        employer.add(employer2);
        employer.add(employer3);
    }
}
abstract class Employer{
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public abstract void add(Employer employer);
    public abstract void delete(Employer employer);
    public List<Employer> employers;
    public void printInfo(){
        System.out.println(name);
    }
    public List<Employer> getEmployers(){
        return employers;
    }
    public  void displayTree(Employer root) {//递归遍历整个树。
        List<Employer> children = root.getEmployers();

        for (Employer employer : children) {
            System.out.println(employer.getName());
            if(employer.getEmployers()!=null){
                for(Employer employer2:employer.getEmployers()){
                    displayTree(employer2);
                }
            }
        }
    }
}
class Programer extends Employer{//相当于leaf
    public Programer(String name){
        setName(name);
        employers=null;//最低端的程序员,能雇佣的只有脑子T T
    }
    @Override
    public void add(Employer employer) {
    }

    @Override
    public void delete(Employer employer) {
    }
    
}
class ProjectManager extends Employer{
    public ProjectManager(String name){
        setName(name);
        employers=new ArrayList<Employer>();
    }
    
    @Override
    public void add(Employer employer) {
        employers.add(employer);
    }

    @Override
    public void delete(Employer employer) {
        employers.remove(employer);
    }
    
}

上述代码定义了一个树形结构,假如我们想定义一个employer的动作,只需要在父类中定义,全部子类重写或者直接继承即可。

2.安全模式测试代码

public class ZuhemoshiTest {
    public static void main(String[] args) {
        Manager manager=new ProjectManager("项目经理");
        Employer employer2=new Programer("程序员1");
        Employer employer3=new Programer("程序员2");
        manager.add(employer2);
        manager.add(employer3);
    }
}
class Employer{
    protected String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
class Programer extends Employer{//相当于leaf
    public Programer(String name){
        setName(name);
    }    
}
abstract class Manager extends Employer{
    public abstract void add(Employer employer);
    public abstract void delete(Employer employer);
    public List<Employer> employers;
    public void printInfo(){
        System.out.println(name);
    }
    public List<Employer> getEmployers(){
        return employers;
    }
    public  void displayTree(Manager root) {
        List<Employer> children = root.getEmployers();

        for (Employer employer : children) {
            if(employer instanceof Manager){
                System.out.println(employer.getName());
                displayTree((Manager)employer);
            }else {
                System.out.println(employer.getName());
            }
        }
    }
}
class ProjectManager extends Manager{
    public ProjectManager(String name){
        setName(name);
        employers=new ArrayList<Employer>();
    }
    
    @Override
    public void add(Employer employer) {
        employers.add(employer);
    }

    @Override
    public void delete(Employer employer) {
        employers.remove(employer);
    }
    
}

3.为了应对组合模式没有实现面向接口编程,个人认为可以通过接口实现。核心代码如下,这个相关资料里没有提到过,不知道对不对。欢迎大神指正。

interface Employ{
    public List<Employ> employs=new ArrayList<Employ>();//接口中声明的变量是final的,表示变量地址不会改变
    void add(Employ employ);
    void remove(Employ employ);
}




















你可能感兴趣的:(一天一种设计模式之八-----组合模式)