装饰者模式
装饰者模式:简单的理解就是在原有对象上包装一层附件动作,且保持包装完后的对象与被包装者属于同一个类族,但是额外附加了该包装类所特定的动作。
其关键点有:
- 包装类对象HAS-A被包装对象;
- 包装类与被被包装对象属于同一个类族,即都有相同的超类型;
- 包装可以嵌套/可以被多次包装,即某被包装者被包装类A包装之后产生的对象还可以继续被其他包装类包装,包括上一层包装类A
包装模式所体现的“对扩展开放,对修改关闭”原则:
- 对扩展开放:通过包装,原被包装对象有了包装类指定的扩展行为,可以用于原被包装对象的场合(当然前提是那是基于接口设计的代码)
- 对修改关闭:不用修改已有的代码即可以实现功能的扩展。
使用包装者模式与使用继承的区别:使用包装者模式可以动态的添加行为,使用继承则是静态的,是编译时确定的。假设使用继承模式,则必须对每一种可能存在的行为组合都写一个专门的类来表示,即你的代码能够表示的行为组合的种类是由你设计的类决定的,客户无法得到你设计之外的组合模式;而使用包装者模式,你只需把所有可能的基本行为写好,而这些行为怎么去组合,则完全由客户根据自己的需要决定。
装饰者模型的缺点:
- 可能会加入大量的小类或者存在很多的对象;
- 对于某些依赖于特定类型的代码的,包装者就会失效。
类模型:
策略模式
策略模式:定义算法族,分别封装起来,让他们之间可以互相替换,以让算法的变化独立于使用算法的客户代码。其出发宗旨就是:封装变的部分!
要点:
- 定义多个算法,即多个实现方案;
- 各个算法之间可以替换,一般实现方式是让所有算法实现某个接口,且在客户代码中针对接口编程;
- 算法的变化独立于使用者:可以更改算法的实现代码,但是使用者代码确不用任何更改;可以设置使用者使用的具体实现算法
使用案例:假使定义一个Coder类,不同的Coder有不同的writeBolg方式,那么根据策略模式的思路,其类模型如下:还可以在Coder中添加set(WriteBlog)方法以动态的设置策略
优势:假使有这么一个需求:有CoderA,COderB,CoderC,COderD四种Coder,其中A,B使用InCnblog,C,D使用InCsdn,那么假使使用继承来解决,那么可能分别需要在CoderA,COderB中以InCnblog的方式重写writeBlog,在CoderC,COderD中以InCsdn的方式重写writeBlog,显然,产生了重复的代码。而且,当以后以InCsdn的实现方案变了,那么就需要在CD两个类中去维护。再进一步,如果CoderB突然想以InCsdn方式写博客了,继承的方式可能就难以应付。而使用策略模式则可以很好的解决这些问题。
观察者模式
观察者模式:定义对象之间的一对多依赖,当一个对象改变状态时,它所有的依赖者都会收到通知并自动更新。
要点:
- 一对多:避免多个对象控制同一个数据
- 可注册可移除:让被观察者与观察者之间的耦合尽量最低
简单的观察者模型:
- 消息更新的方式有两种。一种是pull,即在Oberver中调用getData方法获取自己想要的数据,方便按需索取;一种是push,即在update方法中(此时update则必须有参数),把所有的数据类型都一次性传给Oberver,比较方便,也是用的更多的方式;
- 为什么在observer要有subject的引用:用于移除自己的注册;
- 不要依赖于观察者被通知的顺序:由于我们设计的目的就是松耦合,所以如果subject做了某些改变导致通知的顺序变了,假如在obsever中存在某种对通知顺序的依赖,那么observer则也必须做出相应的改变以适应subject的改变,这样是不符合设计初衷的
- 在java.util.Observable提供观察者模型,http://www.android-doc.com/reference/java/util/Observable.html, 需要注意的事,必须先调用setChanged()才会通知才会有效,因为在notifyObservers的方法中,要先检查changed为true才会通知obervers。这样的设计可以让通知模式有更多弹性,比如对于气象站的源数据数据,可能是实时更新,但是对于观察者来说可能每小时更新一次就够了,那么就可以每一小时调用一次setChanged().