组合模式(结构型)

发布于:2024-05-16 ⋅ 阅读:(147) ⋅ 点赞:(0)

目录

一、前言

二、透明组合模式

三、安全组合模式

四、总结


一、前言

        组合模式(Composite Pattern)是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”得层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

        组合模式由以下角色组成:

Component(抽象组件):

一般是接口或者抽象类,是叶子构件和容器构件对象声明接口,抽象出访问以及管理子构件的方法,可以看做是根节点

Leaf(叶子结点):

在组合中表示叶子节点对象,叶子节点没有子节点,也就没有子构件

Composite(复合节点):

复合节点可以包含子节点,子节点可以是叶子节点,也可以是其他复合节点。可以看做是树枝节点

        整个组合模式的结构图:

二、透明组合模式

        组合模式分为透明和安全两种方式,在透明方式中,抽象组件中会声明所有类中的方法,客户端无法区别树叶对象和树枝对象,对客户端是透明的。但在树叶节点中,本来没有添加、删除放大,但却要实现它,是没有意义的。

        比如公司组织建构,公司有总公司,总公司下有财务部门、技术部门等,还有分公司,分公司也有财务部门,技术部门等。如果按照传统方式,总公司的财务部门、技术部门等需要代码实现,分公司的财务部门、技术部门也需要代码实现,但现实中这些部门的职责差不多,分公司其实可以复用总公司的财务部门、技术部门类。

        根据组合模式,我们便有以下代码实现:

        抽象组件Component类,即根节点:

public abstract class Component {


    abstract void add(Component component);

    abstract void remove(Component component);

    abstract void display(int depth);

    abstract void operation();
}

        复合节点Composite类,即树枝节点:

public class Composite extends Component{

    private List<Component> children = new ArrayList<>();

    private String name;

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

    @Override
    void add(Component component) {
        children.add(component);
    }

    @Override
    void remove(Component component) {
        children.remove(component);
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
        for (Component component : children) {
            component.display(depth + 1);
        }
    }

    @Override
    void operation() {
        for (Component component : children){
            component.operation();
        }
    }
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component{

    private String name;
    public LeafOne(String name) {
        this.name = name;
    }

    @Override
    void add(Component component) {

    }

    @Override
    void remove(Component component) {

    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "财务操作");
    }
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{
    private String name;
    public LeafTwo(String name) {
        this.name = name;
    }

    @Override
    void add(Component component) {

    }

    @Override
    void remove(Component component) {

    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "技术操作");
    }
}

        客户端调用类:

public class Client {

    public static void main(String[] args) {

        Component component = new Composite("北京总公司");
        component.add(new LeafOne("北京总公司财务部门"));
        component.add(new LeafTwo("北京总公司技术部门"));


        Component component1 = new Composite("上海分公司");
        component1.add(new LeafOne("上海分公司财务部门"));
        component1.add(new LeafTwo("上海分公司技术部门"));
        component.add(component1);



        Component component2 = new Composite("深圳分公司");
        component2.add(new LeafOne("深圳分公司财务部门"));
        component2.add(new LeafTwo("深圳分公司技术部门"));
        component.add(component2);

        System.out.println("公司架构:");
        component.display(1);
        System.out.println("职能:");
        component.operation();

    }
}

        运行结果:

三、安全组合模式

        相较于透明方式的组合模式,安全方式主要在抽象组件中不包含添加、删除操作,客户端调用中区分复合节点和叶子节点。

        抽象组件Component类:

public abstract class Component {

    abstract void display(int depth);

    abstract void operation();
}

        复合节点Composite类:

public class Composite extends Component{
    private List<Component> children = new ArrayList<>();

    private String name;

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

    public void add(Component component) {
        children.add(component);
    }

    public void remove(Component component) {
        children.remove(component);
    }
    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
        for (Component component : children) {
            component.display(depth + 1);
        }
    }

    @Override
    void operation() {
        for (Component component : children){
            component.operation();
        }
    }
}

        叶子节点财务部门LeafOne类:

public class LeafOne extends Component {

    private String name;
    public LeafOne(String name) {
        this.name = name;
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "财务操作");
    }
}

        叶子节点财务部门LeafTwo类:

public class LeafTwo extends Component{
    private String name;
    public LeafTwo(String name) {
        this.name = name;
    }

    @Override
    void display(int depth) {
        System.out.println("深度:" + depth + " 名称:" + name);
    }

    @Override
    void operation() {
        System.out.println(name + "技术操作");
    }
}

        客户端调用:

public class Client {
    public static void main(String[] args) {
        Composite composite = new Composite("北京总公司");
        composite.add(new LeafOne("北京总公司财务部门"));
        composite.add(new LeafTwo("北京总公司技术部门"));


        Composite composite1 = new Composite("上海分公司");
        composite1.add(new LeafOne("上海分公司财务部门"));
        composite1.add(new LeafTwo("上海分公司技术部门"));
        composite.add(composite1);



        Composite composite2 = new Composite("深圳分公司");
        composite2.add(new LeafOne("深圳分公司财务部门"));
        composite2.add(new LeafTwo("深圳分公司技术部门"));
        composite.add(composite2);

        System.out.println("公司架构:");
        composite.display(1);
        System.out.println("职能:");
        composite.operation();
    }
}

        运行结果:

四、总结

        优点与缺点

优点:

1、高层模块(客户端)调用简单。组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码

2、节点自由增加,更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”

缺点:

1、在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

2、设计较复杂,客户端需要花更多时间理清类之间的层次关系

3、不容易限制容器中的构件

4、不容易用继承的方法来增加构件的新功能

        使用场景:

        当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式。      

        Spring中IOC就使用到组合模式,通过将组件组合成树形结构,实现了对象的依赖关系管理和生命周期控制。比如Spring中的CompositeCacheManager,Spring用来管理多个CacheManager的复合类。

文件系统:

组合模式可以用来表示文件系统的层次结构,使得客户端可以以统一的方式操作文件和文件夹,例如创建、删除、移动等。

组织机构:

组合模式可以用于表示组织机构的层次结构,例如公司的组织结构可以以树形结构来表示,根节点表示公司,子节点表示部门,叶子节点表示员工。使用组合模式可以统一地管理公司的组织结构,例如添加、删除部门或员工,查找某个部门的员工等。

图形界面控件:

图形界面中的控件可以被看作是一个层次结构,例如窗口控件可以包含按钮控件和文本框控件,按钮控件又可以包含图片控件等。组合模式可以用来表示控件的层次结构,使得客户端可以以统一的方式操作控件,例如添加、删除、遍历等。

菜单和菜单项:

在图形界面中,菜单可以包含菜单项,菜单项可以是子菜单或者普通的操作项。组合模式可以用来表示菜单和菜单项的层次结构,使得客户端可以以统一的方式操作菜单和菜单项,例如添加、删除、遍历等。


网站公告

今日签到

点亮在社区的每一天
去签到