设计模式笔记--装饰模式
2016-01-13 09:13
274 查看
常用设计模式有23中,分为:
创建型模式(主要用于创建对象)
1、单例模式 2、工厂方法模式
3、抽象工厂模式 4、建造者模式 5、原型模式
行为型模式 (主要用于描述对象或类是怎样交互和怎样分配职责)
1、模板方法模式 2、中介者模式 3、命令模式
4、责任链模式 5、策略模式 6、迭代器模式
7、观察者模式 8、备忘录模式 9、访问者模式 10、状态模式 11、解释器模式
结构型模式(主要用于处理类或对象的组合)
1、代理模式 2、装饰模式
3、适配器模式 4、组合模式 5、外观模式(门面模式) 6、享元模式
7、桥梁模式
装饰模式
装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
在类图中,有四个角色需要说明:
● Component抽象构件
Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,如上面的成绩单。
注意 在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。
● ConcreteComponent 具体构件
ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
● Decorator装饰角色
一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。
● 具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其他东西
通用代码
先看抽象构件,如代码清单17-10所示。
具体构件如代码清单17-11所示。
装饰角色通常是一个抽象类,如代码清单17-12所示。
当然了,若只有一个装饰类,则可以没有抽象装饰角色,直接实现具体的装饰角色即可。
具体的装饰类如代码清单17-13所示。
注意 原始方法和装饰方法的执行顺序在具体的装饰类是固定的,可以通过方法重载实现多种执行顺序。
我们通过Client类来模拟高层模块的耦合关系,
看看装饰模式是如何运行的,如代码清单17-14所示。
实例 成绩单
其中Decorator的作用是封装SchoolReport类,如果大家还记得代理模式,那么很容易看懂这个类图,装饰类的作用也就是一个特殊的代理类,真实的执行者还是被代理的角色FouthGradeSchoolReport,如代码清单17-6所示。
装饰类还是把动作的执行委托给需要装饰的对象,Decorator抽象类的目的很简单,就是要让子类来封装SchoolReport的子类,怎么封装?重写report方法!
先看HighScoreDecorator实现类,如代码清单17-7所示。
重写了report方法,先调用具体装饰类的装饰方法reportHighScore,然后再调用具体构件的方法,我们再来看怎么汇报学校排序情况SortDecorator代码,如代码清单17-8所示。
看看老爸怎么看成绩单的,如代码清单17-9所示。
优点
● 装饰类和被装饰类可以独立发展,而不会相互耦合
● 装饰模式是继承关系的一个替代方案。
● 装饰模式可以动态地扩展一个实现类的功能
缺点
多层的装饰是比较复杂的 ,因此,尽量减少装饰类的数量,以便降低系统的复杂度。
使用场景
● 需要扩展一个类的功能,或给一个类增加附加功能。
● 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。
装饰模式是对继承的有力补充。
继承是静态地给类增加功能,而装饰模式则是动态地增加功能
装饰模式可以给我们很好的帮助,通过装饰模式重新封装一个类,而不是通过继承来完成,简单点说,三个继承关系Father、Son、GrandSon三个类,我要在Son类上增强一些功能怎么办?我想你会坚决地顶回去!不允许
为什么呢?你增强的功能是修改Son类中的方法吗?增加方法吗?对GrandSon的影响呢?特别是GrandSon有多个的情况,你会怎么办?这个评估的工作量就够你受的,所以这是不允许的,
那还是要解决问题的呀,怎么办?通过建立SonDecorator类来修饰Son,相当于创建了一个新的类,这个对原有程序没有变更,通过扩展很好地完成了这次变更。
创建型模式(主要用于创建对象)
1、单例模式 2、工厂方法模式
3、抽象工厂模式 4、建造者模式 5、原型模式
行为型模式 (主要用于描述对象或类是怎样交互和怎样分配职责)
1、模板方法模式 2、中介者模式 3、命令模式
4、责任链模式 5、策略模式 6、迭代器模式
7、观察者模式 8、备忘录模式 9、访问者模式 10、状态模式 11、解释器模式
结构型模式(主要用于处理类或对象的组合)
1、代理模式 2、装饰模式
3、适配器模式 4、组合模式 5、外观模式(门面模式) 6、享元模式
7、桥梁模式
装饰模式
装饰模式(Decorator Pattern)是一种比较常见的模式,其定义如下:
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
在类图中,有四个角色需要说明:
● Component抽象构件
Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,如上面的成绩单。
注意 在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。
● ConcreteComponent 具体构件
ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
● Decorator装饰角色
一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。
● 具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其他东西
通用代码
先看抽象构件,如代码清单17-10所示。
<span style="font-size:18px;">代码清单17-10 抽象构件 public abstract class Component { //抽象的方法 public abstract void operate(); }</span>
具体构件如代码清单17-11所示。
<span style="font-size:18px;">代码清单17-11 具体构件 public class ConcreteComponent extends Component { //具体实现 @Override public void operate() { System.out.println("do Something"); } } </span>
装饰角色通常是一个抽象类,如代码清单17-12所示。
<span style="font-size:18px;">public abstract class Decorator extends Component { private Component component = null; //通过构造函数传递被修饰者 public Decorator(Component _component){ this.component = _component; } //委托给被修饰者执行 @Override public void operate() { this.component.operate(); } }</span>
当然了,若只有一个装饰类,则可以没有抽象装饰角色,直接实现具体的装饰角色即可。
具体的装饰类如代码清单17-13所示。
<span style="font-size:18px;">public class ConcreteDecorator1 extends Decorator { //定义被修饰者 public ConcreteDecorator1(Component _component){ super(_component); } //定义自己的修饰方法 private void method1(){ System.out.println("method1 修饰"); } //重写父类的Operation方法 public void operate(){ this.method1(); super.operate(); } } </span>
<span style="font-size:18px;">public class ConcreteDecorator2 extends Decorator { //定义被修饰者 public ConcreteDecorator2(Component _component){ super(_component); } //定义自己的修饰方法 private void method2(){ System.out.println("method2修饰"); } //重写父类的Operation方法 public void operate(){ super.operate(); this.method2(); } }</span>
注意 原始方法和装饰方法的执行顺序在具体的装饰类是固定的,可以通过方法重载实现多种执行顺序。
我们通过Client类来模拟高层模块的耦合关系,
看看装饰模式是如何运行的,如代码清单17-14所示。
<span style="font-size:18px;">代码清单17-14 场景类 public class Client { public static void main(String[] args) { Component component = new ConcreteComponent(); //第一次修饰 component = new ConcreteDecorator1(component); //第二次修饰 component = new ConcreteDecorator2(component); //修饰后运行 component.operate(); } } </span>
实例 成绩单
其中Decorator的作用是封装SchoolReport类,如果大家还记得代理模式,那么很容易看懂这个类图,装饰类的作用也就是一个特殊的代理类,真实的执行者还是被代理的角色FouthGradeSchoolReport,如代码清单17-6所示。
<span style="font-size:18px;">public abstract class Decorator extends SchoolReport{ //首先我要知道是哪个成绩单 private SchoolReport sr; //构造函数,传递成绩单过来 public Decorator(SchoolReport sr){ this.sr = sr; } //成绩单还是要被看到的 public void report(){ this.sr.report(); } //看完还是要签名的 public void sign(String name){ this.sr.sign(name); } }</span>
装饰类还是把动作的执行委托给需要装饰的对象,Decorator抽象类的目的很简单,就是要让子类来封装SchoolReport的子类,怎么封装?重写report方法!
先看HighScoreDecorator实现类,如代码清单17-7所示。
<span style="font-size:18px;">代码清单17-7 最高成绩修饰 public class HighScoreDecorator extends Decorator { //构造函数 public HighScoreDecorator(SchoolReport sr){ super(sr); } //我要汇报最高成绩 private void reportHighScore(){ System.out.println("这次考试语文最高是75,数学是78,自然是80"); } //我要在老爸看成绩单前告诉他最高成绩,否则等他一看,就抡起扫帚揍我,我哪里还有机会说啊 @Override public void report(){ this.reportHighScore(); super.report(); } }</span>
重写了report方法,先调用具体装饰类的装饰方法reportHighScore,然后再调用具体构件的方法,我们再来看怎么汇报学校排序情况SortDecorator代码,如代码清单17-8所示。
<span style="font-size:18px;">代码清单17-8 排名情况修饰 public class SortDecorator extends Decorator { //构造函数 public SortDecorator(SchoolReport sr){ super(sr); } //告诉老爸学校的排名情况 private void reportSort(){ System.out.println("我是排名第38名..."); </span>
看看老爸怎么看成绩单的,如代码清单17-9所示。
<span style="font-size:18px;">代码清单17-9 老爸查看修饰后的成绩单 public class Father { public static void main(String[] args) { //把成绩单拿过来 SchoolReport sr; //原装的成绩单 sr = new FouthGradeSchoolReport(); //加了最高分说明的成绩单 sr = new HighScoreDecorator(sr); //又加了成绩排名的说明 sr = new SortDecorator(sr); //看成绩单 sr.report(); //然后老爸一看,很开心,就签名了 sr.sign("老三"); } } </span>
优点
● 装饰类和被装饰类可以独立发展,而不会相互耦合
● 装饰模式是继承关系的一个替代方案。
● 装饰模式可以动态地扩展一个实现类的功能
缺点
多层的装饰是比较复杂的 ,因此,尽量减少装饰类的数量,以便降低系统的复杂度。
使用场景
● 需要扩展一个类的功能,或给一个类增加附加功能。
● 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。
装饰模式是对继承的有力补充。
继承是静态地给类增加功能,而装饰模式则是动态地增加功能
装饰模式可以给我们很好的帮助,通过装饰模式重新封装一个类,而不是通过继承来完成,简单点说,三个继承关系Father、Son、GrandSon三个类,我要在Son类上增强一些功能怎么办?我想你会坚决地顶回去!不允许
为什么呢?你增强的功能是修改Son类中的方法吗?增加方法吗?对GrandSon的影响呢?特别是GrandSon有多个的情况,你会怎么办?这个评估的工作量就够你受的,所以这是不允许的,
那还是要解决问题的呀,怎么办?通过建立SonDecorator类来修饰Son,相当于创建了一个新的类,这个对原有程序没有变更,通过扩展很好地完成了这次变更。
相关文章推荐
- Extjs学习----------动态载入js文件(减轻浏览器的压力)
- 商务英语句型11
- Quick-Cocos2dx-- 资源热更新2
- 紫金桥组态软件的DL/T 645-2007驱动
- ES6学习——类语法:Symbol.species在实例创建中的应用
- 在基于tomcat的web project中加载dll文件的方法(来源于实际项目经验)
- KMP算法
- meaven 下载Jar包
- 查看oracle数据库的连接数以及用户
- git学习笔记
- linux生产服务器有关网络状态的优化措施
- 七分养护三分维修 关注车辆的生命周期保养
- 苦逼也聊模式--(1)--简单工厂
- vs:如何添加.dll文件
- CocoaPods更新慢的问题
- *Permutations II
- JavaScript类型检测之typeof 和 instanceof 的缺陷与优化
- 【Android的事件处理】-----基于监听的事件处理
- malloc、calloc、realloc的区别
- linux下SVN服务器如何搭建和使用