设计模式——结构型模式(三)

Composite(组合模式)

目标

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

结构

通用结构图

一个组合模式中有着容器以及实现对象,但是它们都是一个Component的各子类。

Android中View层次图

Android中的View,可以作为一种容器来存放其他的View,也可以自己作为一个单独的View。

适用情形

  1. 需要表示对象的部分-整体层次结构;

  2. 用户可以忽略组合对象与单个对象的不同,统一地调度操作对象。

    对于用户来说,该对象是否是组合对象并不重要。例如一般的文件管理器中,对于文件夹或者文件都有着复制、粘贴等功能,内部实现稍有区别。

参与者

  • Component

    为组合的对象声明接口并且实现所有方法的默认方法,并且拥有一个能够访问和管理所有Component子组件的方法以及一个可选择的、能够访问到父组件的一个方法。

  • Leaf

    在组合结构中表示没有容器对象行为的组件。

  • Composite

    存储、管理、操作子部件,并且在Component接口中实现相应功能。

  • Client

    通过Component操作组合结构。

效果

  1. 定义了包含基本对象和组合对象的类层次结构。这样可以让用户将所需要的组件无限递归地组合添加下去,使得用户可以在所有的地方用到组合对象。

  2. 简化客户代码。用户不需要关心处理的是一个叶结点还是一个组合容器,对于用户来说,都可以用同样的方法来实现业务。

  3. 使设计更容易加入新的组件。

实现细节

  1. 最大化Component接口。为了让用户真正的不能感觉到自己是在使用一个Leaf或者Composite,Component接口应该尽可能多的支持更多的公共方法。这里就会发生一个矛盾,一般的来说一个类只应该定义那些对自己或者子类有意义的方法,但是Component却要在很多地方提供很多的缺省操作。

  2. 实现子类管理的位置。如果你在Component接口中定义了Add、Remove方法,这样的话Leaf也会有这个方法,用户可能会对Leaf执行很多无意义的操作;如果你只在Composite中定义Add、Remove方法,用户就会意识到自己是在使用一个Composite而不是一个Leaf。一般地来说,推荐使用前一种方法。否则用户就需要将一个Component强行转换为Composite类,这样会出现用户将Leaf转换的可能,一种可能的方法是在Component中提供一个getComposite方法,若是在Compsite中调用便会返回自己,Leaf中便返回NULL即可。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
abstract class Goods{
private Linklist<Goods> children;
private Goods parent;
abstract public void contains(Goods good);
abstract public void values();
public void setParent(Goods parent) {
this.parent = parent;
}
public Goods getParent() {
return parent;
}
}
class Gold extends Goods{
@Override
public void contains(Goods good) {
// DO NOTHING
}
@Override
public void values() {
System.out.println("This costs a LOT!");
}
}
class Box extends Goods{
@Override
public void contains(Goods good) {
children.add(good);
good.setParent(this);
}
@Override
public void values() {
System.out.println("This costs litte");
}
}
public class Client{
public static void main(String args[]) {
Goods good1 = new Box();
Goods good2 = new Gold();
Goods good3 = new Box();
good1.contains(good2);
good2.contains(good3);
good3.values();
good2.values();
}
}

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2018 Alex's Blog All Rights Reserved.

Yifeng Tang hält Urheberrechtsansprüche.