1、 装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。

2、组合和继承的区别

继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。

组合。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。

与继承相比,组合关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象。

3、装饰者模式的优缺点

优点

1、装饰者模式可以提供比继承更多的灵活性

2、可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。

3、通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。

4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

缺点

1、会产生很多的小对象,增加了系统的复杂性

2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

4、装饰者的使用场景

  1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。  当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

以上内容来自网络

5、UML图(Astah/jude)下载地址:http://pan.baidu.com/s/1eQiVePc

6、示例:

装饰者基类

 package com.xinye.test.decoration;
/**
* 食物基类
* @author xinye
*
*/
public abstract class Food { protected String desc; public abstract String getDesc();
}

鸡肉

 package com.xinye.test.decoration;
/**
* 鸡肉
* @author xinye
*
*/
public class Chicken extends Food {
public Chicken(){
desc = "鸡肉";
}
@Override
public String getDesc() {
return desc;
} }

鸭肉

 package com.xinye.test.decoration;
/**
* 鸭肉
* @author xinye
*
*/
public class Duck extends Food {
public Duck(){
desc = "鸭肉";
}
@Override
public String getDesc() {
return desc;
} }

装饰者基类

 package com.xinye.test.decoration;
/**
*
* @author xinye
*
*/
public abstract class FoodDecoration extends Food { @Override
public abstract String getDesc(); }

蒸-装饰者

 package com.xinye.test.decoration;
/**
* 蒸食物
* @author xinye
*
*/
public class SteamedFood extends FoodDecoration { private Food food; public SteamedFood(Food f){
this.food = f;
} @Override
public String getDesc() {
return getDecoration() + food.getDesc();
} private String getDecoration(){
return "蒸";
}
}

烤-装饰者

 package com.xinye.test.decoration;
/**
* 烤食物
* @author xinye
*
*/
public class RoastFood extends FoodDecoration { private Food food; public RoastFood(Food f){
this.food = f;
} @Override
public String getDesc() {
return getDecoration() + food.getDesc();
} private String getDecoration(){
return "烤";
}
}

客户端

 package com.xinye.test.decoration;
/**
* 客户端
* @author xinye
*
*/
public class Client {
public static void main(String[] args) {
// 测试单纯的食物
Food f1 = new Chicken();
System.out.println(f1.getDesc()); System.out.println("----------------------");
// 测试单重修饰的食物
RoastFood rf = new RoastFood(f1);
System.out.println(rf.getDesc()); System.out.println("----------------------");
// 测试多重修饰的食物
SteamedFood sf = new SteamedFood(rf);
System.out.println(sf.getDesc());
}
}

执行结果:
鸡肉
----------------------
烤鸡肉
----------------------
蒸烤鸡肉

修饰者模式(装饰者模式,Decoration)的更多相关文章

  1. Head First--设计模式(装饰者模式)

    从现在开始,我将以写一个小软件的方式来进行模式识别的学习,包含需求分析,功能模块设计,原理图设计,程序实现这个几个部分,可能具体的模式模块不可能都包括在内. 需求分析:星巴兹咖啡店已经遍布全世界的很多 ...

  2. 7.js模式-装饰者模式

    1. 装饰者模式 给对象动态增加职责的方式称为装饰者模式. Function.prototype.before = function(beforefn){ var _self = this; retu ...

  3. JS模式--装饰者模式

    在Javascript中动态的给对象添加职责的方式称作装饰者模式. 下面我们通常遇到的例子: var a = function () { alert(1); };//改成: var a = funct ...

  4. java模式—装饰者模式

    装饰者模式 1.意图: 动态地给一个对象添加一些额外的职责.就增加功能来说, Decorator模式相比生成子类更为灵活.该模式以对客 户端透明的方式扩展对象的功能. 2.适用环境 (1)在不影响其他 ...

  5. Decorator模式 装饰器模式

    Android 使用了装饰器模式 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加 ...

  6. Python3-设计模式-装饰器模式

    装饰器模式 动态的给原有对象添加一些额外的职责,面向切面编程(AOP),多用于和主业务无关,但又必须的业务,如:登录认证.加锁.权限检查等 Python代码实现示例 需求点: 1.在old_func( ...

  7. JS模式--装饰者模式(用AOP动态改变函数的参数)

    Function.prototype.before = function (beforefn) { var _self = this; return function () { beforefn.ap ...

  8. java设计模式之 装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...

  9. java IO之 字符流 (字符流 = 字节流 + 编码表) 装饰器模式

    字符流 计算机并不区分二进制文件与文本文件.所有的文件都是以二进制形式来存储的,因此, 从本质上说,所有的文件都是二进制文件.所以字符流是建立在字节流之上的,它能够提供字符 层次的编码和解码.列如,在 ...

随机推荐

  1. js的变量使用<bean><list:write>赋值时需加' '

    script的变量使用<bean><list:write>赋值时需加' ',如:var code ='<bean:write name="target" ...

  2. UIScrollView详解

    1.UIScrollView常用属性 contentSize属性--该属性表示滚动的内容的范围大小,是CGPoint类型的. 说明: 默认超出UIScrollView的可视区域的内容是不显示的.相当于 ...

  3. phpcms开启、关闭在线编辑模板的方法

    打开 caches/configs/system.php 文件 找到 'tpl_edit'=> 0,//是否允许在线编辑模板 修改此行代码中的数字为 1或0 即可

  4. 添加App启动页面

    记录下自己在设置app启动页面时遇到的问题. 先写下自己完整的步骤吧. iPhone Portrait iOS 8-Retina HD 5.5 (1242×2208) @3xiPhone Portra ...

  5. Webpack使用教程四(Loaders)

    Loaders是webpack最有用的特性之一,通过Loaders,webpack可以预处理源码文件中的Json文件或者将包含新特性的Javascript代码转换成浏览器能处理的JavaScript代 ...

  6. 作业七:团队项目——Alpha版本冲刺阶段

      本次作业为期三周时间,要求各组结合所选项目并阅读教材<构建之法>第六章内容,完成项目的Alpha版本.本阶段的主要内容如下:(20分) 1. 每天组织一次站立会议,讨论每个成员的昨天进 ...

  7. Linux 进程间通信(二) 管道

    Linux 进程间通信-管道 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及 ...

  8. [游戏学习25] MFC 橡皮筋画线效果

    >_<:这是给出窗口内外不同情况的处理展示的例子. >_<:MouseCap.h #include<afxwin.h> class CMyApp :public C ...

  9. centos 6.5卸载Mysql

    yum remove  mysql mysql-server mysql-libs mysql-server

  10. LeadTools Android 入门教学——运行第一个Android Demo

    LeadTools 有很多Windows平台下的Demo,非常全面,但是目前开发手机应用的趋势也越来越明显,LeadTools也给大家提供了10个Android的Demo,这篇文章将会教你如何运行第一 ...