博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Android源代码设计模式解析与实战》读书笔记
阅读量:7183 次
发布时间:2019-06-29

本文共 10160 字,大约阅读时间需要 33 分钟。

1.定义

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

2.使用场景

(1)表示对象的部分-总体层次结构时。

(2)从一个总体中可以独立出部分模块或功能的场景。

3.UML类图

这里写图片描写叙述

(1)Component:抽象根节点,为组合中的对象声明接口。在适当的情况下。实现全部类共同拥有接口的缺省行为。

声明一个接口用于訪问和管理Component的子节点。可在递归结构中定义一个接口,用于訪问一个父节点,并在合适的情况下实现它。

(2)Composite:定义有子节点的那些枝干节点行为,存储子节点,在Component接口中实现与子节点有关的操作。

(3)Leaf:在组合中表示叶子节点对象,叶子节点没有子节点。在组合中定义节点对象的行为。

(4)Client:通过Component接口操纵组合节点的对象。

如图这样的将组合所使用的方法所有定义在抽象类的方式称为透明的组合模式,假设将Component中的Add、Remove、GetChild去除,仅仅在Composite中单独加入。这样的方式称为安全的组合模式。

然而后者违背了依赖倒置原则。

4.简单实现

以文件和目录这种文件系统为例

文件和目录的抽象类:(Component)

public abstract class Dir {    /**     * 声明一个List成员变量来储存目录下的全部元素     */    protected List
dirs = new ArrayList
();
private String name;
//当前文件或目录名
public
Dir(String name) {
this.name = name; }
/** * 加入一个文件或目录 * * @param dir 文件或目录 */
public
abstract
void
addDir(Dir dir);
/** * 移除一个文件或目录 * * @param dir 文件或目录 */
public
abstract
void
rmDir(Dir dir);
/** * 清空目录下全部元素 */
public
abstract
void
clear();
/** * 输出目录目录结构 */
public
abstract
void
print();
/** * 获取目录下全部的文件或目录 * * @return 目录下全部的文件或目录 */
public
abstract List
getFiles();
/** * 获取文件或目录名 * * @return 文件或目录名 */
public String
getName(){
return name; }}
  • 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
  • 53

表示目录的类:(Composite)

public class Folder extends Dir{    public Folder(String name) {        super(name);    }    @Override    public void addDir(Dir dir) {        dirs.add(dir);    }    @Override    public void rmDir(Dir dir) {        dirs.remove(dir);    }    @Override    public void clear() {        dirs.clear();    }    @Override    public void print() {        System.out.print(getName() + "(");        Iterator
iter = dirs.iterator(); while (iter.hasNext()) { Dir dir = iter.next(); dir.print(); if(iter.hasNext()){ System.out.print(", "); } } System.out.print(")"); } @Override public List
getFiles() {
return dirs; }}
  • 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

表示目录的类:(Leaf)

public class File extends Dir{    public File(String name) {        super(name);    }    @Override    public void addDir(Dir dir) {        throw new UnsupportedOperationException("文件对象不支持该操作!

"</span>); } <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">rmDir</span>(Dir dir) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsupportedOperationException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"文件对象不支持该操作!"</span>); } <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">clear</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsupportedOperationException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"文件对象不支持该操作!

"</span>); } <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">print</span>() { System.out.print(getName()); } <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> List<Dir> <span class="hljs-title" style="box-sizing: border-box;">getFiles</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> UnsupportedOperationException(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"文件对象不支持该操作!

"</span>); } } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>

客户类:

public class Client {    public static void main(String[] args) {        //构造一个文件夹对象表示C盘根文件夹        Dir diskC = new Folder("C");        //C盘根文件夹下有一个文件Log.txt        diskC.addDir(new File("Log.txt"));        //C盘根文件夹下有三个文件夹Windows、PerfLogs、Program File        Dir dirWin = new Folder("Windows");        //Windows文件夹下有文件explorer.exe        dirWin.addDir(new File("explorer.exe"));        diskC.addDir(dirWin);        //PerfLogs文件夹        Dir dirPer = new Folder("PerfLogs");        //PerfLogs文件夹下有文件null.txt        dirPer.addDir(new File("null.txt"));        diskC.addDir(dirPer);        //Program File文件夹        Dir dirPro = new Folder("Program File");        //Program File文件夹下有文件ftp.txt        dirPro.addDir(new File("ftp.txt"));        diskC.addDir(dirPro);        //打印出文件结构        diskC.print();    }}
  • 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

结果:

C(Log.txt, Windows(explorer.exe), PerfLogs(null.txt), Program File(ftp.txt))
  • 1

5.Android源代码中的模式实现

1.View和ViewGroup的嵌套组合

View和ViewGroup的结构非常像上面的UML类图,只是View的视图层级使用的是安全的组合模式。ViewGroup有对View的addView、removeView、getChildAt等方法。想必大家也非常熟悉。

6.总结

1.长处

(1)组合模式能够清楚地定义分层次的复杂对象,表示对象的所有或部分层次。他让高层模块忽略了层次的差异。方便对整个层次结构进行控制。

(2)简化了高层模块的代码。

(3)在组合模式中添加新的枝干构件和叶子构件都非常方便。无须对现有类库进行改动,符合“开闭原则”。

(4)对树形结构的控制变得简单。

2.缺点

组合模式不easy限制组合中的构件。由于大多数情况下,它们都来自于同样的抽象层,此时。必须进行类型检查来实现,这个实现过程较为复杂。

你可能感兴趣的文章
UITextView for Code
查看>>
AlertPickerView
查看>>
ISColumnsController
查看>>
部分JVM参数解释
查看>>
mysql优化技巧
查看>>
java 里关于二叉树排序的问题
查看>>
每天一个linux命令(13):less 命令
查看>>
ios项目常用目录分包结构
查看>>
ThinkPHP中的动态缓存(S方法)和快速缓存(F方法)
查看>>
GoLang练习实例100之006----斐波那契数列
查看>>
富文本编辑器焦点
查看>>
机器学习认知
查看>>
iOS应用程序生命周期(前后台切换,应用的各种状态)详解
查看>>
$GLOBALS ["HTTP_RAW_POST_DATA"]为空
查看>>
谷歌浏览器中,js首次打印,图片没显示
查看>>
设计自己解析XML字段,并反射到对应类
查看>>
linux 下安装maven + git直接编译项目
查看>>
oracle用sum函数实现累加
查看>>
java中创建对象的方法
查看>>
UNIX/Linux系统取证之信息采集案例
查看>>