Java设计模式8:组合模式(Composite)

组合模式(Composite)

意图

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

适用性

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

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

结构

这里写图片描述

典型的Composite对象结构

这里写图片描述

Component

为组合的对象声明接口

适当情况下,实现所有类共有接口的缺省行为

声明一个接口用于访问和管理Component的子组件

在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现

Leaf

在组合中表示叶节点对象,叶节点没有子节点

在组合中定义图元对象的行为

Composite

定义所有子部件的部件行为

存储子部件

在Component接口中实现与子部件有关的操作

Client

通过Component接口操纵组合部件的对象

实现

既然说是像一个树状结构,首先想到的就是公司的部门架构,如下

Component
package composite;

/**
 * @Author fitz.bai
 * @Date 2018/8/29 20:59
 */
public abstract class Company {
    private String name;

    public Company() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected abstract void add(Company company);

    protected abstract void remove(Company company);

    protected abstract void display(int depth);
}

Composite

package composite;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author fitz.bai
 * @Date 2018/8/29 21:01
 */
public class ConcreteCompany extends Company {

    private List<Company> companyList;

    public ConcreteCompany() {
        companyList = new ArrayList<>();
    }

    public ConcreteCompany(String name) {
        super(name);
        companyList = new ArrayList<>();
    }

    @Override
    protected void add(Company company) {
        companyList.add(company);
    }

    @Override
    protected void remove(Company company) {
        companyList.remove(company);
    }

    @Override
    protected void display(int depth) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            stringBuilder.append("-");
        }
        System.out.println(stringBuilder.toString() + this.getName());
        for (Company c : companyList) {
            c.display(depth + 2);
        }
    }
}

Leaf

package composite;

/**
 * @Author fitz.bai
 * @Date 2018/8/29 21:06
 */
public class OCDepartment extends Company {

    public OCDepartment() {
    }

    public OCDepartment(String name) {
        super(name);
    }

    @Override
    protected void add(Company company) {

    }

    @Override
    protected void remove(Company company) {

    }

    @Override
    protected void display(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            sb.append("-");
        }
        System.out.println(new String(sb) + this.getName());
    }
}

package composite;

/**
 * @Author fitz.bai
 * @Date 2018/8/29 21:06
 */
public class TechDepartment extends Company {

    public TechDepartment() {
    }

    public TechDepartment(String name) {
        super(name);
    }

    @Override
    protected void add(Company company) {

    }

    @Override
    protected void remove(Company company) {

    }

    @Override
    protected void display(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            sb.append("-");
        }
        System.out.println(new String(sb) + this.getName());
    }
}

Client

package composite;

/**
 * @Author fitz.bai
 * @Date 2018/8/29 20:58
 */
public class Client {
    public static void main(String[] args) {
        Company root = new ConcreteCompany("Fitz总公司");
        root.add(new OCDepartment("OC部门"));
        root.add(new TechDepartment("技术部门"));

        Company shanghai = new ConcreteCompany("Fitz上海分公司");
        shanghai.add(new OCDepartment("上海OC部门"));
        shanghai.add(new TechDepartment("上海技术部门"));

        Company yangpu = new ConcreteCompany("Fitz上海杨浦分公司");
        yangpu.add(new OCDepartment("上海杨浦OC部门"));
        yangpu.add(new TechDepartment("上海杨浦技术部门"));

        root.add(shanghai);
        root.add(yangpu);

        root.display(0);

    }
}

/**
Fitz总公司
--OC部门
--技术部门
--Fitz上海分公司
----上海OC部门
----上海技术部门
--Fitz上海杨浦分公司
----上海杨浦OC部门
----上海杨浦技术部门
*/

安全模式和透明模式

从上面的Compoent看出,我们把用来组合使用的方法都方法哦了抽象类中,不管是叶子对象还是树枝对象都有相同的结构,这种方式叫做透明模式

安全模式就是在抽象组件中之定义一些默认的属性和行为,把树枝接点和叶子结点全部彻底分开,上面的例子,我们可以把Company类中只保留共有的display方法,而在ConcreteCompany中还可以有add和remove方法,具体到部门之后(例如OC department)是叶子结点,无法add和remove,因此只保留display方法,这就是安全模式

优点

1、清楚地表示分层次的复杂对象且增加删除构件更容易。

2、叶子对象也可以被组合容器对象,容器对象又可以添加多个叶子对象,这样不断递归下去,可以形成表达复杂的树形结构。

3、更容易在组合体内加入对象,客户端不必因为加入了新的对象构件而更改原有代码。

缺点

增加新构件时,我们很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。

猜你喜欢

转载自blog.csdn.net/qq_22798455/article/details/82193174