zoukankan      html  css  js  c++  java
  • 结构型模式

    组合模式(Composite Pattern)

    简介

    组合模式,也叫部分整体模式,用于把一组相似的对象当作一个单一的对象,组合模式依据树形结构来组合对象,用来表示部分以及整体层次。属于结构型模式,创建了对象组的树形结构。

    意图

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

    解决问题

    主要解决:在树形结构问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
    如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。
    关键代码:树枝和叶子实现统一接口,树枝内部组合该接口。

    特点

    • 优点
    1. 高层模块调用简单;
    2. 节点自由增加。
    • 缺点
      使用组合模式时,叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

    • 组合模式有两种实现方式

    1. 透明方式
      在Component中声明所有用来管理子对象的方法,其中包括Add, Remove等,这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处是叶节点和枝节点对于外界没有区别,具备完全一致的行为接口。但问题也在这里,因为Leaf类本身不具备Add, Remove功能,实现它没有意义。

    2. 不透明方式
      也是安全的方式,在Component接口中,不去声明Add和Remove方法,那么子类Leaf也不需要去实现。

    组合模式 VS 建造者模式

    组合模式和建造者模式都是由子对象构成整体,那么它们有什么区别呢?

    1. 组成部分类型
      组合模式强调组成整体的部分,都是同一类型。建造者模式主要是为了表示,通过子部件组装称为完成产品,不要求子部件都是同一类型。
    2. 组成部分和整体的关系
      组合模式体现是整体与部分的层次关系,依据树形结构来组合对象。建造者模式体现的是这个过程,对客户屏蔽创建对象的复杂性。
    3. 组成部分的可变性
      组合模式如果缺少某个部分,整体依然是整体,而且容易添加、删除部分;建造者模式如果缺少某个部分,很可能无法正常工作,无法删除子部件。

    应用实例

    1.算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作数、操作符和另一个操作数。
    2.JAVA AWT和SWING中,对于Button和Checkbox是树叶,Container是树枝。

    通用类图

    透明方式类图

    不透明方式类图

    实现代码

    以不透明方式为例

    1. 新建Company抽象类,声明管理子对象的方法
    // Company.java
    public abstract class Company {
          protected String name;
          
          public Company(String name) {
                this.name = name;
          }
          
          public abstract void add(Company company);
          public abstract void remove(Company company);
          public abstract void display(int dept); // 显示
          public abstract void lineOfDuty(); // 职责
    }
    
    1. 新建具体的公司类ConcreteCompany实现Company
    // ConcreteCompany.java
    public class ConcreteCompany extends Company {
          private List<Company> children = new ArrayList<Company>();
          
          public ConcreteCompany(String name) {
                super(name);
          }
          
          @Override
          public void add(Company company) {
                children.add(company);
          }
          @Override
          public void remove(Company company) {
                children.remove(company);
          }
          @Override
          public void display(int dept) {
                int tmp = dept;
                while(tmp -- > 0)
                      System.out.print("-");
                System.out.println(name);
                
                for(Company component: children) {
                      component.display(dept + 2);
                }
          }
          @Override
          public void lineOfDuty() {
                for(Company component: children) {
                      component.lineOfDuty();
                }
          }
    }
    
    1. 新建叶子节点HRDepartment, FinanceDepartment
    // HRDepartment.java
    public class HRDepartment extends Company {
          public HRDepartment(String name) {
                super(name);
          }
          @Override
          public void add(Company company) {
          }
          @Override
          public void remove(Company company) {
          }
          @Override
          public void display(int dept) {
                while(dept -- > 0)
                      System.out.print("-");
                System.out.println(name);
          }
          @Override
          public void lineOfDuty() {
                System.out.println(name + " 员工招聘管理培训");
          }
    }
    
    // FinanceDepartment.java
    public class FinanceDepartment extends Company {
          public FinanceDepartment(String name) {
                super(name);
          }
          @Override
          public void add(Company company) {
          }
          @Override
          public void remove(Company company) {
          }
          @Override
          public void display(int dept) {
                while(dept -- > 0)
                      System.out.print("-");
                System.out.println(name);
          }
          @Override
          public void lineOfDuty() {
                System.out.println(name + " 公司财务收支管理");
          }
    }
    
    1. 新建客户端类,使用组合模式创建叶子节点和Component节点,并打印层次结构图和职责
    // Client.java
    public class Client {
          public static void main(String[] args) {
                ConcreteCompany root = new ConcreteCompany("北京总公司");
                root.add(new HRDepartment("总公司人力资源部"));
                root.add(new FinanceDepartment("总公司财务部"));
                
                ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
                comp.add(new HRDepartment("华东分公司人力资源部"));
                comp.add(new FinanceDepartment("华东分公司财务部"));
                root.add(comp);
                
                ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
                comp1.add(new HRDepartment("南京办事处人力资源部"));
                comp1.add(new FinanceDepartment("南京办事处财务部"));
                root.add(comp1);
                
                ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
                comp2.add(new HRDepartment("杭州办事处人力资源部"));
                comp2.add(new FinanceDepartment("杭州办事处财务部"));
                root.add(comp2);
                
                System.out.println("结构图:");
                root.display(1);
                
                System.out.println("职责:");
                root.lineOfDuty();
          }
    }
    

    运行结果

    结构图:
    -北京总公司
    ---总公司人力资源部
    ---总公司财务部
    ---上海华东分公司
    -----华东分公司人力资源部
    -----华东分公司财务部
    ---南京办事处
    -----南京办事处人力资源部
    -----南京办事处财务部
    ---杭州办事处
    -----杭州办事处人力资源部
    -----杭州办事处财务部
    职责:
    总公司人力资源部 员工招聘管理培训
    总公司财务部 公司财务收支管理
    华东分公司人力资源部 员工招聘管理培训
    华东分公司财务部 公司财务收支管理
    南京办事处人力资源部 员工招聘管理培训
    南京办事处财务部 公司财务收支管理
    杭州办事处人力资源部 员工招聘管理培训
    杭州办事处财务部 公司财务收支管理
    
  • 相关阅读:
    Ajax实现表格实时编辑
    自定义简单分页
    有趣的 0
    关于AJAX的一些事
    JQ中的FormData对象 ajax上传文件
    订单导出
    javaScript事件委托
    javascript递归函数
    详解javascript中this的工作原理
    详解JavaScript对象继承方式
  • 原文地址:https://www.cnblogs.com/fortunely/p/14265077.html
Copyright © 2011-2022 走看看