组合模式_组合模式

本文介绍了组合模式,它允许将对象组合成树形结构,表现“整体 - 部分”层次。阐述了组合与聚合关系的区别,介绍了组合模式的角色,包括抽象根节点、树枝节点和叶子类。还讲解了透明和安全两种实现方式,分析了其优缺点及应用场景。
组合模式

组合模式(composite pattern)也称为“整体-部分(Part-Whole)”模式,允许你将对象组合成树形结构来表现"整体-部分"层次结构,使得客户对单个对象和组合对象使用具有一致性,属于结构性模式。

组合关系和聚合关系的区别:

1、组合关系:比如车和轮胎,也可以认为是全体 - 部分的关系,车报废时,轮胎也跟着报废 。(具有相同的生命周期)

part-of关系,父类拥有子类,子类不能独立于父类存在。

2、聚合关系:班级和学生是一种聚合关系。一个班级,可以有学生,也可以没有学生;反过来,当我们把班级解散,学生仍然存在。(具有不同的生命周期)

has-a关系,父类包含子类,子类可以独立于父类存在。

组合模式一般用来描述整体和部分的关系,它将对象组织到树形结构中,最顶层的节点称为根节点,根节点下面包含树枝节点和叶子节点,树枝节点下面又可以包含树枝节点和叶子节点。

ad812c3ef7ade14a97951ca5da277b53.png

组合模式的包含3个角色:

抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认的属性和行为;

树枝节点(Composite):定义了树枝节点的节点,组合树枝节点和叶子节点形成一个树形结构;

叶子类(Leaf):叶子节点的对象,其下再无分支,是系统层次遍历的最小单元。

组合模式在代码的具体的实现上,有两种不同的方式,分别是透明组合模式和安全组合模式。

组合模式应用场景

1、希望客户端可用忽略组合对象和单个对象的差异;

2、对象层次具备整体和部分,呈现树形结构;

在我们的生活中组合模式也非常常见,比如树形菜单,操作系统目录结构,公司组织架构等。

透明组合模式

透明组合模式是把公共方法定义在Component 中,这样做的好处是客户端无需分辨是叶子节点和树枝节点,它们具有一样的接口,UML类图如下:

e84612571adb56ee4f41f7d8ddc941c9.png

Component类:

public abstract class Component {  protected String name;  protected int level;  public Component(String name,int level) {    this.name = name;    this.level = level;  }  abstract void print();  abstract public void add(Component component);  abstract public void remove(Component component);}

Composite类:

public class Composite extends Component {  private List child;  public Composite(String name, int level) {    super(name, level);    child = new ArrayList<>();  }  @Override  void print() {    for (int i = 0; i < level; i++) {      System.out.print("##");    }    System.out.println("Composite:" + name);    for (Component component : child) {      component.print();    }  }  @Override  public void add(Component component) {    child.add(component);  }  @Override  public void remove(Component component) {    child.remove(component);  }}

Leaf类:

public class Leaf extends Component {  public Leaf(String name, int level) {    super(name, level);  }  @Override  void print() {    for (int i = 0; i < level; i++) {      System.out.print("##");    }    System.out.println("leaf:" + name);  }  @Override  public void add(Component component) {    // 牺牲透明性换取单一职责原则,这样就不用考虑是叶子节点还是组合节点    throw new UnsupportedOperationException();  }  @Override  public void remove(Component component) {    throw new UnsupportedOperationException();  }}

Client类:

public class Client {  public static void main(String[] args) {    Composite root = new Composite("root",0);    Component node1 = new Leaf("1",1);    Component node2 = new Composite("2",1);    Component node3 = new Leaf("3",1);    root.add(node1);    root.add(node2);    root.add(node3);    Component node21 = new Leaf("21",2);    Component node22 = new Composite("22",2);    node2.add(node21);    node2.add(node22);    Component node221 = new Leaf("221",3);    node22.add(node221);    root.print();  }}

运行结果:

Composite:root##leaf:1##Composite:2####leaf:21####Composite:22######leaf:221##leaf:3

透明组合模式是把所有公共方法都定义在Component中,这样做的好处是客户端无需分辨是叶子节点还是树枝节点,它们是一样的接口;缺点是叶子节点会继承一些用不到的方法,这种方式违背了接口隔离原则。

下面我们来看下安全组合模式的写法。

安全组合模式

安全组合模式只是规定系统各个层次的最基础的一致行为,而把组合(树节点)本身的方法(添加、删除)放大自身当中,UML类图如下:

7de3f21e0c04d937e3494a8ef27023dd.png

修改Component类:

public abstract class Component {  protected String name;  protected int level;  public Component(String name,int level) {    this.name = name;    this.level = level;  }  abstract void print();}

修改Leaf类:

public class Leaf extends Component {  public Leaf(String name, int level) {    super(name, level);  }  @Override  void print() {    for (int i = 0; i < level; i++) {      System.out.print("##");    }    System.out.println("leaf:" + name);  }}

从上面可以看出,Component减少了添加和删除节点方法,因为叶子节点是不需要的,没有必要实现了。

组合模式的优缺点

优点:

   1、清楚定义了分层次的复杂对象,表示对象的全部和部分的层次

   2、客户端不必担心层次的差异,方便对整个层次结构的控制

   3、简化客户端代码

   4、符合开闭原则

缺点:

   1、限制类的时候会比较复杂

   2、设计变得更加抽象

 -END- 

关注公众号,不错过每一篇原创干货

4ec5b3b55a74479129bbf43983974a07.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值