diff --git a/.DS_Store b/.DS_Store index 03e360c..73c2895 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/README.md b/README.md index 022985a..28ed445 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,6 @@ ## 简述 该项目通过分析Android系统中的设计模式来提升大家对设计模式的理解,从源码的角度来剖析既增加了对Android系统本身的了解,也从优秀的设计中领悟模式的实际运用以及它适用的场景,避免在实际开发中的生搬硬套。如果你对面向对象的六大开发原则还不太熟悉,那么在学习模式之前先学习一下[面向对象的六大原则](oop-principles/oop-principles.md)是非常有必要的。 -**每一个模式在Android源码中可能有很多个实现,因此我们为每个模式创建一个文件夹,就是为了同一个模式可以有多个人分析,这样我们就可以从更多的源码中学习对应的模式,具体请参考[编写步骤](#steps)。我们的原则是通过分析这些源码不仅要学会设计模式本身,而且要通过学习该模式深入到Android源码层的实现,这样不仅学了设计模式,也增加了我们对于Android源码的了解。** - -**QQ交流群: 413864859,希望大家踊跃参与进来。** - - -## 编写步骤 -1. 填写[任务表](#schedule); -2. 在模式对应的文件夹下以你的用户名建立一个文件夹,例如我分析的是适配器模式,那么我在adapter目录下建立一个mr.simple文件夹; -3. 将template.md拷贝一份到adapter/mr.simple目录下,并且重命名为readme.md; -4. 所需图片统一放到你的用户名文件夹的images目录下,例如adapter/mr.simple/images; -5. 按照[template.md](template.md)的格式将模式分析的markdown文件编写完毕; -6. 提交本地修改,将本地的提交push线上。 - -样例大家可以参考[Mr.Simple的单例模式分析](singleton/mr.simple)。 - - ## 任务表 ( 一期截止 2015.3.20 ) | 模式名 | 分析者 | 状态 | @@ -27,60 +11,17 @@ | [Builder模式](builder/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu)| 完成 | | [外观模式](facade/elsdnwn) | [elsdnwn](https://github.com/elsdnwn)、[Mr.Simple](https://github.com/bboyfeiyu)| 完成 | | [模板方法](template-method/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu) | 完成 | -| [适配器模式](adapter/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu) | 完成 | -| [观察者模式](observer/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu) | 完成 | | [策略模式](strategy/gkerison) | [GKerison](https://github.com/GKerison) | 完成 | | [代理模式](proxy/singwhatiwanna) | [singwhatiwanna](https://github.com/singwhatiwanna) | 完成 | -| [组合模式](composite/tiny-times) | [tiny-times](https://github.com/tiny-times) | 撒丫子赶稿中 | -| [装饰模式](decorator/tiny-times) | [tiny-times](https://github.com/tiny-times) | 撒丫子赶稿中 | -| [享元模式](flyweight/lvtea0105) | [lvtea0105](https://github.com/lvtea0105) | 撒丫子赶稿中 | | [迭代器模式](iterator/haoxiqiang) | [Haoxiqiang](https://github.com/Haoxiqiang)| 完成 | | [责任链模式](chain-of-responsibility/AigeStudio) | [AigeStudio](https://github.com/AigeStudio)| 完成 | -| [状态模式](state/Thinan) | [Thinan](https://www.github.com/Thinan)| 撒丫子赶稿中 | -| [命令模式](command/lijunhuayc) | [lijunhuayc](https://github.com/lijunhuayc)| 待审核 | +| [命令模式](command/lijunhuayc) | [lijunhuayc](https://github.com/lijunhuayc)| 完成 | | [桥接模式](bridge/shen0834) | [shen0834](https://github.com/shen0834)| 完成 | | [原型模式](prototype/mr.simple) | [Mr.Simple](https://github.com/bboyfeiyu)| 完成 | - - -## 目前无人认领的模式 -| 模式名 | -| ------------- | -| 中介者模式 | -| 备忘录模式 | -| 解释器模式 | -| 访问者模式 | - -## 模式与文件夹对应列表 -| 模式名 | 文件夹 | -| ------------- |:-------------:| -| 适配器模式 | [adapter](adapter) | -| 抽象工厂模式 | [abstract-factory](abstract-factory) | -| 桥接模式 | [bridge](bridge) | -| Builder模式 | [builder](builder) | -| 责任链模式 | [chain-of-responsibility](chain-of-responsibility) | -| 命令模式 | [command](command) | -| 组合模式 | [composite](composite) | -| 装饰模式 | [decorator](decorator) | -| 外观模式 | [facade](facade) | -| 工厂方法模式 | [factory-method](factory-method) | -| 享元模式 | [flyweight](flyweight) | -| 解释器模式 | [interpreter](interpreter) | -| 迭代器模式 | [iterator](iterator) | -| 中介者模式 | [mediator](mediator) | -| 备忘录模式 | [memento](memento) | -| 观察者模式 | [observer](observer) | -| 原型模式 | [prototype](prototype) | -| 代理模式 | [proxy](proxy) | -| 单例模式 | [singleton](singleton) | -| 状态模式 | [state](state) | -| 策略模式 | [strategy](strategy) | -| 模板方法模式 | [template-method](template-method) | -| 访问者模式 | [visitor](visitor) | - ## 参考资料 -* [GOF的设计模式:可复用面向对象软件的基础](http://pan.baidu.com/s/1i3zjaIx) -* [设计模式之禅](http://pan.baidu.com/s/1sjjZCvj) -* [Java与模式](http://pan.baidu.com/s/1i3sxzyH) +* [GOF的设计模式:可复用面向对象软件的基础](http://item.jd.com/10057319.html) +* [设计模式之禅](http://item.jd.com/11414555.html) +* [Java与模式](http://item.jd.com/10094286.html) * [java-design-patterns](https://github.com/iluwatar/java-design-patterns) * [Java之美[从菜鸟到高手演变]之设计模式](http://blog.csdn.net/zhangerqing/article/details/8194653) diff --git a/adapter/.DS_Store b/adapter/.DS_Store index 1615c38..5008ddf 100644 Binary files a/adapter/.DS_Store and b/adapter/.DS_Store differ diff --git a/adapter/mr.simple/.DS_Store b/adapter/mr.simple/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/adapter/mr.simple/.DS_Store and /dev/null differ diff --git a/adapter/mr.simple/readme.md b/adapter/mr.simple/readme.md index 4250337..6a8835a 100644 --- a/adapter/mr.simple/readme.md +++ b/adapter/mr.simple/readme.md @@ -131,7 +131,7 @@ public class ObjectAdapter implements FiveVolt { ```java public class Test { public static void main(String[] args) { - ClassAdapter adapter = new ClassAdapter(); + ObjectAdapter adapter = new ObjectAdapter(new Volt220()); System.out.println("输出电压 : " + adapter.getVolt5()); } } @@ -388,4 +388,4 @@ ListView覆写了AbsListView中的layoutChilden函数,在该函数中根据布   在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。 ### 缺点 -* 过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 \ No newline at end of file +* 过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是A接口,其实内部被适配成了B接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。 diff --git a/builder/mr.simple/readme.md b/builder/mr.simple/readme.md index 7a219d5..bb6f7ca 100644 --- a/builder/mr.simple/readme.md +++ b/builder/mr.simple/readme.md @@ -73,8 +73,6 @@ package com.dp.example.builder; /** * Apple电脑 - * @author mrsimple - * */ public class AppleComputer extends Computer { @@ -101,63 +99,11 @@ public class AppleComputer extends Computer { package com.dp.example.builder; -/** - * builder抽象类 - * - * @author mrsimple - * - */ -public abstract class Builder { - // 设置CPU核心数 - public abstract void buildCPU(int core); - - // 设置内存 - public abstract void buildRAM(int gb); - - // 设置操作系统 - public abstract void buildOs(String os); - - // 创建Computer - public abstract Computer create(); - -} - -package com.dp.example.builder; - -/** - * Apple电脑 - * @author mrsimple - * - */ -public class AppleComputer extends Computer { - - protected AppleComputer() { - - } - - @Override - public void setCPU(int core) { - mCpuCore = core; - } - - @Override - public void setRAM(int gb) { - mRamSize = gb; - } - - @Override - public void setOs(String os) { - mOs = os; - } - -} package com.dp.example.builder; /** * builder抽象类 - * - * @author mrsimple * */ public abstract class Builder { diff --git a/chain-of-responsibility/AigeStudio/readme.md b/chain-of-responsibility/AigeStudio/readme.md index b5c6a49..453005e 100644 --- a/chain-of-responsibility/AigeStudio/readme.md +++ b/chain-of-responsibility/AigeStudio/readme.md @@ -50,7 +50,7 @@ public class SimpleResponsibility { } } ``` -谁敢说没用过上面这种结构体的站出来我保证不打屎他,没用过swith至少if-eles用过吧,if-eles都没用过你怎么知道github的……上面的这段代码其实就是一种最最简单的责任链模式,其根据request的值进行不同的处理。当然这只是个不恰当的例子来让大家尽快对责任链模式有个简单的理解,因为可能很多童鞋第一次听说这个模式,而人对未知事物总是恐惧的,为了消除大家的这种恐惧,我将大家最常见的code搬出来相信熟悉的代码对大家来说有一种亲切的感觉,当然我们实际应用中的责任链模式绝逼不是这么Mr.Simple,但是也不会复杂不到哪去。责任链模式,顾名思义,必定与责任Responsibility相关,其实质呢就像上面定义中说的那样一个请求(比如上面代码中的request值)沿着一条“链”(比如上面代码中我们的switch分支语句)传递,当某个处于“链”上的处理者(case定义的条件)处理它时完成处理。其实现实生活中关于责任者模式的例子数不胜数,最常见的就是工作中上下级之间的责任请求关系了。比如: +谁敢说没用过上面这种结构体的站出来我保证不打屎他,没用过swith至少if-else用过吧,if-else都没用过你怎么知道github的……上面的这段代码其实就是一种最最简单的责任链模式,其根据request的值进行不同的处理。当然这只是个不恰当的例子来让大家尽快对责任链模式有个简单的理解,因为可能很多童鞋第一次听说这个模式,而人对未知事物总是恐惧的,为了消除大家的这种恐惧,我将大家最常见的code搬出来相信熟悉的代码对大家来说有一种亲切的感觉,当然我们实际应用中的责任链模式绝逼不是这么Mr.Simple,但是也不会复杂不到哪去。责任链模式,顾名思义,必定与责任Responsibility相关,其实质呢就像上面定义中说的那样一个请求(比如上面代码中的request值)沿着一条“链”(比如上面代码中我们的switch分支语句)传递,当某个处于“链”上的处理者(case定义的条件)处理它时完成处理。其实现实生活中关于责任者模式的例子数不胜数,最常见的就是工作中上下级之间的责任请求关系了。比如: >程序猿狗屎运被派出去异国出差一周,这时候就要去申请一定的差旅费了,你心里小算一笔加上各种车马费估计大概要个两三万,于是先向小组长汇报申请,可是大于一千块小组长没权利批复,于是只好去找项目主管,项目主管一看妈蛋这么狠要这么多我只能批小于五千块的,于是你只能再跑去找部门经理,部门经理看了下一阵淫笑后说没法批我只能批小于一万的,于是你只能狗血地去跪求老总,老总一看哟!小伙子心忒黑啊!老总话虽如此但还是把钱批给你了毕竟是给公司办事,到此申请处理完毕,你也可以屁颠屁颠地滚了。 如果把上面的场景应用到责任链模式,那么我们的request请求就是申请经费,组长主管经理老总们就是一个个具体的责任人他们可以对请求做出处理但是他们只能在自己的责任范围内处理该处理的请求,而程序猿只是个底层狗请求者向责任人们发起请求…………苦逼的猿。 diff --git a/observer/.DS_Store b/observer/.DS_Store index 1615c38..5008ddf 100644 Binary files a/observer/.DS_Store and b/observer/.DS_Store differ diff --git a/observer/mr.simple/.DS_Store b/observer/mr.simple/.DS_Store deleted file mode 100644 index c3b5fbc..0000000 Binary files a/observer/mr.simple/.DS_Store and /dev/null differ diff --git a/observer/mr.simple/images/.DS_Store b/observer/mr.simple/images/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/observer/mr.simple/images/.DS_Store and /dev/null differ diff --git a/observer/mr.simple/images/image-1.png b/observer/mr.simple/images/image-1.png deleted file mode 100644 index e9e69d1..0000000 Binary files a/observer/mr.simple/images/image-1.png and /dev/null differ diff --git a/observer/mr.simple/images/image-2.png b/observer/mr.simple/images/image-2.png deleted file mode 100644 index 7213ede..0000000 Binary files a/observer/mr.simple/images/image-2.png and /dev/null differ diff --git a/observer/mr.simple/images/subscriber.png b/observer/mr.simple/images/subscriber.png deleted file mode 100644 index 535413c..0000000 Binary files a/observer/mr.simple/images/subscriber.png and /dev/null differ diff --git a/observer/mr.simple/images/uml.png b/observer/mr.simple/images/uml.png deleted file mode 100644 index 33d4f8f..0000000 Binary files a/observer/mr.simple/images/uml.png and /dev/null differ diff --git a/observer/mr.simple/readme.md b/observer/mr.simple/readme.md deleted file mode 100644 index a1337b8..0000000 --- a/observer/mr.simple/readme.md +++ /dev/null @@ -1,306 +0,0 @@ -Android设计模式源码解析之观察者模式 -==================================== -> 本文为 [Android 设计模式源码解析](https://github.com/simple-android-framework/android_design_patterns_analysis) 中 观察者模式 分析 -> Android系统版本: 2.3 -> 分析者:[Mr.Simple](https://github.com/bboyfeiyu),分析状态:未完成,校对者:[Mr.Simple](https://github.com/bboyfeiyu),校对状态:未开始 - - -## 1. 模式介绍 - -### 模式的定义 -定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。 - - -### 模式的使用场景 -* 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系; -* 事件多级触发场景; -* 跨系统的消息交换场景,如消息队列、事件总线的处理机制。 - - -## 2. UML类图 -![uml](images/uml.png) - -### 角色介绍 -* 抽象主题 (Subject) 角色 -抽象主题角色把所有观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。 - -* 具体主题 (ConcreteSubject) 角色 -将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。 - -* 抽象观察者 (Observer) 角色 -为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。 - -* 具体观察者 (ConcreteObserver) 角色 -存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。 - - -## 3. 模式的简单实现 -### 简单实现的介绍 -[AndroidWeekly](http://androidweekly.net/)是一个每周都会发布关于Android新技术、开源库、招聘信息等内容的网站,在这里我们可以看到最新的技术,最牛X的工程师,经常逛逛这类网站不仅能够开阔我们的眼界,也能让我们接触到最前言的科技信息。这其实就是一个RSS系统,用户订阅Android Weekly的文章,每当有更新的时候将新的内容推送给订阅用户。这不就是观察者模式吗?观察者模式的另一个名字叫做发布-订阅模式,下图就是我订阅AndroidWeekly之后他们发来的确认邮件。下面让我们来简单模拟一下AndroidWeekly的发布过程吧! - -![android-weekly](images/subscriber.png) -### 实现源码 - -```java -/** - * 程序员是观察者 - * - * @author mrsimple - */ -public class Coder implements Observer { - public String name ; - - public Coder(String aName) { - name = aName ; - } - - @Override - public void update(Observable o, Object arg) { - System.out.println( "Hi, " + name + ", AndroidWeekly更新啦, 内容 : " + arg); - } - - @Override - public String toString() { - return "码农 : " + name; - } - -} - - -/** - * AndroidWeekly这个网站是被观察者,它有更新所有的观察者 (这里是程序员) 都会接到相应的通知. - * - * @author mrsimple - */ -public class AndroidWeekly extends Observable { - - public void postNewPublication(String content) { - // 标识状态或者内容发生改变 - setChanged(); - // 通知所有观察者 - notifyObservers(content); - } -} - -// 测试代码 -public class Test { - public static void main(String[] args) { - // 被观察的角色 - AndroidWeekly androidWeekly = new AndroidWeekly(); - // 观察者 - Coder mrsimple = new Coder("mr.simple"); - Coder coder1 = new Coder("coder-1"); - Coder coder2 = new Coder("coder-2"); - Coder coder3 = new Coder("coder-3"); - - // 将观察者注册到可观察对象的观察者列表中 - androidWeekly.addObserver(mrsimple); - androidWeekly.addObserver(coder1); - androidWeekly.addObserver(coder2); - androidWeekly.addObserver(coder3); - - // 发布消息 - androidWeekly.postNewPublication("新的一期AndroidWeekly来啦!"); - } - -} - -``` - -输出结果: - -``` -Hi, coder-3, AndroidWeekly更新啦, 内容 : 新的一期AndroidWeekly来啦! -Hi, coder-2, AndroidWeekly更新啦, 内容 : 新的一期AndroidWeekly来啦! -Hi, coder-1, AndroidWeekly更新啦, 内容 : 新的一期AndroidWeekly来啦! -Hi, mr.simple, AndroidWeekly更新啦, 内容 : 新的一期AndroidWeekly来啦! -``` - -可以看到所有订阅了AndroidWeekly的用户都受到了更新消息,一对多的订阅-发布系统这么简单就完成了。 - -这里Observer是抽象的观察者角色,Coder扮演的是具体观察者的角色;Observable对应的是抽象主题角色,AndroidWeekly则是具体的主题角色。Coder是具体的观察者,他们订阅了AndroidWeekly这个具体的可观察对象,当AndroidWeekly有更新时,会遍历所有观察者 ( 这里是Coder码农 ),然后给这些观察者发布一个更新的消息,即调用Coder中的update方法,这样就达到了1对多的通知功能。Observer和Observable都已经内置在jdk中,可见观察者模式在java中的重要性。 - - - -## Android源码中的模式实现 -ListView是Android中最重要的控件,没有之一。而ListView最重要的一个点就是Adapter,在[Android设计模式源码解析之适配器(Adapter)模式](../../adapter/mr.simple)中我们分析了Adapter模式,在我们往ListView添加数据后,我们都会调用一个方法: notifyDataSetChanged(), 这是为什么呢? 今天我们就来揭开它的神秘面纱。 - -第一步我们就跟进这个方法notifyDataSetChanged方法,这个方法定义在BaseAdapter中,代码如下: - -```java -public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { - // 数据集观察者 - private final DataSetObservable mDataSetObservable = new DataSetObservable(); - - // 代码省略 - - public void registerDataSetObserver(DataSetObserver observer) { - mDataSetObservable.registerObserver(observer); - } - - public void unregisterDataSetObserver(DataSetObserver observer) { - mDataSetObservable.unregisterObserver(observer); - } - - /** - * Notifies the attached observers that the underlying data has been changed - * and any View reflecting the data set should refresh itself. - * 当数据集用变化时通知所有观察者 - */ - public void notifyDataSetChanged() { - mDataSetObservable.notifyChanged(); - } -} - -``` - -我们一看BaseAdapter上述代码,大体有了这么一个了解,原来BaseAdapter是一个观察者模式! -那么BaseAdapter是如何运作的? 这些观察者又是什么呢?我们一步一步来分析。 - -我们先跟到mDataSetObservable.notifyChanged()函数中看看。 - -```java -/** - * A specialization of Observable for DataSetObserver that provides methods for - * invoking the various callback methods of DataSetObserver. - */ -public class DataSetObservable extends Observable { - /** - * Invokes onChanged on each observer. Called when the data set being observed has - * changed, and which when read contains the new state of the data. - */ - public void notifyChanged() { - synchronized(mObservers) { - // 调用所有观察者的onChanged方式 - for (int i = mObservers.size() - 1; i >= 0; i--) { - mObservers.get(i).onChanged(); - } - } - } - // 代码省略 -} -``` -恩,代码很简单,就是在mDataSetObservable.notifyChanged()中遍历所有观察者,并且调用它们的onChanged方法。 - -那么这些观察者是从哪里来的呢?首先ListView通过setAdapter方法来设置Adapter,我们看看相关代码。 - -```java - @Override - public void setAdapter(ListAdapter adapter) { - // 如果已经有了一个adapter,那么先注销该Adapter对应的观察者 - if (mAdapter != null && mDataSetObserver != null) { - mAdapter.unregisterDataSetObserver(mDataSetObserver); - } - - // 代码省略 - - super.setAdapter(adapter); - - if (mAdapter != null) { - mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); - mOldItemCount = mItemCount; - // 获取数据的数量 - mItemCount = mAdapter.getCount(); - checkFocus(); - // 注意这里 : 创建一个一个数据集观察者 - mDataSetObserver = new AdapterDataSetObserver(); - // 将这个观察者注册到Adapter中,实际上是注册到DataSetObservable中 - mAdapter.registerDataSetObserver(mDataSetObserver); - - // 代码省略 - } else { - // 代码省略 - } - - requestLayout(); - } -``` -可以看到在设置Adapter时会构建一个AdapterDataSetObserver,这不就是我们上面所说的观察者么,最后将这个观察者注册到adapter中,这样我们的被观察者、观察者都有了。一般来说我们的数据集会放到Adapter中,例如 : - -```java -public abstract class UserAdapter extends BaseAdapter { - // 数据集 - protected List mDataSet = new LinkedList(); - protected Context mContext = null; - - public CommonAdapter(Context context, List dataSet) { - this.mDataSet = dataSet; - this.mContext = context; - } -} -``` -这个时候可能你就有点晕了? AdapterDataSetObserver是什么?它是如何运作的?那么我就先来看看AdapterDataSetObserver吧。 - -AdapterDataSetObserver定义在ListView的父类AbsListView中,代码如下 : - -```java - class AdapterDataSetObserver extends AdapterView.AdapterDataSetObserver { - @Override - public void onChanged() { - super.onChanged(); - if (mFastScroller != null) { - mFastScroller.onSectionsChanged(); - } - } - - @Override - public void onInvalidated() { - super.onInvalidated(); - if (mFastScroller != null) { - mFastScroller.onSectionsChanged(); - } - } - } -``` -它由继承自AbsListView的父类AdapterView的AdapterDataSetObserver, 代码如下 : - -```java - class AdapterDataSetObserver extends DataSetObserver { - - private Parcelable mInstanceState = null; - // 上文有说道,调用Adapter的notifyDataSetChanged的时候会调用所有观察者的onChanged方法,核心实现就在这里 - @Override - public void onChanged() { - mDataChanged = true; - mOldItemCount = mItemCount; - // 获取Adapter中数据的数量 - mItemCount = getAdapter().getCount(); - - // Detect the case where a cursor that was previously invalidated has - // been repopulated with new data. - if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null - && mOldItemCount == 0 && mItemCount > 0) { - AdapterView.this.onRestoreInstanceState(mInstanceState); - mInstanceState = null; - } else { - rememberSyncState(); - } - checkFocus(); - // 重新布局ListView、GridView等AdapterView组件 - requestLayout(); - } - - // 代码省略 - - public void clearSavedState() { - mInstanceState = null; - } - } -``` -到这里我们就知道了,当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged函数,这个函数又会调用DataSetObservable的notifyChanged函数,这个函数会调用所有观察者 (AdapterDataSetObserver) 的onChanged方法。这就是一个观察者模式! - -**最后我们再捋一捋,AdapterView中有一个内部类AdapterDataSetObserver,在ListView设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中,这个就是一个观察者。而Adapter中包含一个数据集可观察者DataSetObservable,在数据数量发生变更时开发者手动调用AdapternotifyDataSetChanged,而notifyDataSetChanged实际上会调用DataSetObservable的notifyChanged函数,该函数会遍历所有观察者的onChanged函数。在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。** - -| ![img1](images/image-1.png)| ![img1](images/image-2.png) | -|----------------------------|-----------------------------| -| 图1 | 图2 | - - -## 4. 杂谈 -ListView主要运用了Adapter和观察者模式使得可扩展性、灵活性非常强,而耦合度却很低,这是我认为设计模式在Android源码中优秀运用的典范。那么为什么Android架构师们会这么设计ListView,它们如何达到低耦合、高灵活性呢?这个留给大家思考吧,如果有时间我再分享我的看法。 - -### 优点 -* 观察者和被观察者之间是抽象耦合 - -### 缺点 -* 观察者模式需要考虑一下开发效率和运行效率问题,一个被观察者,多个观察者,开发和调试就会比较复杂,而且在 Java 中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。 diff --git a/oop-principles/oop-principles.md b/oop-principles/oop-principles.md index af07c77..af9333d 100644 --- a/oop-principles/oop-principles.md +++ b/oop-principles/oop-principles.md @@ -142,7 +142,7 @@ public class BasicNetwork implements Network { ### 3.2 示例 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。 -第二章节中的BasicNetwork实现类依赖于HttpStack接口( 抽象 ),而不依赖于HttpClientStack与HurlStack实现类 ( 细节 ),这就是典型的依赖倒置原则的体现。加入BasicNetwork直接依赖了HttpClientStack,那么HurlStack就不能传递给了,除非HurlStack继承自HttpClientStack。但这么设计明显不符合逻辑,HurlStack与HttpClientStack并没有任何的is-a的关系,而且即使有也不能这么设计,因为HttpClientStack是一个具体类而不是抽象,如果HttpClientStack作为BasicNetwork构造函数的参数,那么以为这后续的扩展都需要继承自HttpClientStack。这简直是一件不可忍受的事了! +第二章节中的BasicNetwork实现类依赖于HttpStack接口( 抽象 ),而不依赖于HttpClientStack与HurlStack实现类 ( 细节 ),这就是典型的依赖倒置原则的体现。假如BasicNetwork直接依赖了HttpClientStack,那么HurlStack就不能传递给了,除非HurlStack继承自HttpClientStack。但这么设计明显不符合逻辑,HurlStack与HttpClientStack并没有任何的is-a的关系,而且即使有也不能这么设计,因为HttpClientStack是一个具体类而不是抽象,如果HttpClientStack作为BasicNetwork构造函数的参数,那么以为这后续的扩展都需要继承自HttpClientStack。这简直是一件不可忍受的事了! ### 3.3 优点 @@ -443,4 +443,4 @@ public class DiskBasedCache implements Cache { ## 杂谈 -面向对象六大原则在开发过程中极为重要,如果能够很好地将这些原则运用到项目中,再在一些合适的场景运用一些前人验证过的模式,那么开发出来的软件在一定程度上能够得到质量保证。其实稍微一想,这几大原则最终就化为这么几个关键词: 抽象、单一职责、最小化。那么在实际开发过程中如何权衡、实践这些原则,笔者也在不断地学习、摸索。我想学习任何的事物莫过于实践、经验与领悟,在这个过程中希望能够与大家分享知识、共同进步。 \ No newline at end of file +面向对象六大原则在开发过程中极为重要,如果能够很好地将这些原则运用到项目中,再在一些合适的场景运用一些前人验证过的模式,那么开发出来的软件在一定程度上能够得到质量保证。其实稍微一想,这几大原则最终就化为这么几个关键词: 抽象、单一职责、最小化。那么在实际开发过程中如何权衡、实践这些原则,笔者也在不断地学习、摸索。我想学习任何的事物莫过于实践、经验与领悟,在这个过程中希望能够与大家分享知识、共同进步。 diff --git a/prototype/.DS_Store b/prototype/.DS_Store index 2b359bc..b4dd642 100644 Binary files a/prototype/.DS_Store and b/prototype/.DS_Store differ diff --git a/singleton/.DS_Store b/singleton/.DS_Store index b9ad643..230323f 100644 Binary files a/singleton/.DS_Store and b/singleton/.DS_Store differ diff --git a/singleton/mr.simple/.DS_Store b/singleton/mr.simple/.DS_Store index 8320c41..b52ada2 100644 Binary files a/singleton/mr.simple/.DS_Store and b/singleton/mr.simple/.DS_Store differ diff --git a/singleton/mr.simple/images/singleton-mr.simple-uml.png b/singleton/mr.simple/images/singleton-mr.simple-uml.png index 3ad8df2..571e5f3 100644 Binary files a/singleton/mr.simple/images/singleton-mr.simple-uml.png and b/singleton/mr.simple/images/singleton-mr.simple-uml.png differ