浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上。继续设计模式之路。这次讨论的模式,是
装饰者模式(Decorator Pattern)
装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对象增加新的特性,而不影响这个对象的类(allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class)。
装饰者模式,主要用处是,灵活方便地增加特性到特定的对象上。请看下面的例子:
/**
* Coffee interface defines the functionality of Coffee implemented by decorator
* @author YYC
*
*/
public interface ICoffee { double getCost(); String getIngredients(); } /**
* extension of a simple coffee without any extra ingredients
* @author YYC
*
*/
public class SimpleCoffee implements ICoffee{ public double getCost() {
return 1;
} public String getIngredients() {
return "Coffee";
} } /**
* abstract decorator class - note that it implement Coffee interface
* @author YYC
*
*/
public abstract class CoffeDecorator implements ICoffee { protected final ICoffee decoratedCoffee;
protected String ingredientSeparator = ","; public CoffeDecorator(ICoffee decoratedCoffee) {
this.decoratedCoffee = decoratedCoffee;
} public double getCost(){
return decoratedCoffee.getCost();
} public String getIngredients(){
return decoratedCoffee.getIngredients();
} }
首先对于装饰者模式而已,一个公共的接口是必须的,在这里是ICoffee,代表咖啡的抽象接口。然后需要有一个简单的实现类以及一个装饰者的抽象类,作为具体装饰者的父类。接下来的是具体的装饰者类:
/**
* Decorator Milk that mixes milk with coffee
* @author YYC
*
*/
public class Milk extends CoffeDecorator { public Milk(ICoffee decoratedCoffee) {
super(decoratedCoffee);
} public double getCost() {
return super.getCost() + 0.5;
} public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Milk";
} } /**
* @author YYC
* Decorator Sprinkles that mixes sprinkles with coffee
*/
public class Sprinkles extends CoffeDecorator { public Sprinkles(ICoffee decoratedCoffee) {
super(decoratedCoffee);
} public double getCost() {
return super.getCost() + 1.2;
} public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Sprinkles";
} }
具体的装饰者类,继承抽象装饰者类,并具体实现抽象装饰者类的方法,达到将新的特性(milk/sprinkles)加到原来的类(coffee)的目的。
public class Main { public static void main(String[] args) { ICoffee c = new SimpleCoffee();
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); c = new Milk(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); c = new SimpleCoffee();
c = new Sprinkles(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); c=new SimpleCoffee();
c = new Milk(new Sprinkles(c));
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); } } /*
* output:
* Cost: 1.0; Ingredients: Coffee
* Cost: 1.5; Ingredients: Coffee,Milk
* Cost: 2.2; Ingredients: Coffee,Sprinkles
* Cost: 2.7; Ingredients: Coffee,Sprinkles,Milk
*/
抽象类理解起来并不困难,而且相当实用,很多时候比创建子类更加灵活。在Java里java.io.BufferedReader/FileReader/Reader都有使用这个模式。
以下情况使用Decorator模式
1. 需要扩展一个类的功能,或给一个类添加附加职责。
2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
优点:
1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点:
1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
参考:
http://javapapers.com/design-patterns/decorator-pattern/
http://www.cnblogs.com/god_bless_you/archive/2010/06/10/1755212.html
浅谈设计模式--装饰者模式(Decorator Pattern)的更多相关文章
- 设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法
装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716 ...
- 设计模式 - 装饰者模式(Decorator Pattern) 具体解释
装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者 ...
- C#设计模式——装饰者模式(Decorator Pattern)
一.例子在软件开发中,我们往往会想要给某一类对象增加不同的功能.比如要给汽车增加ESP.天窗或者定速巡航.如果利用继承来实现,就需要定义无数的类,Car,ESPCar,CCSCar,SunRoofCa ...
- 浅谈设计模式--建造器模式(Builder Pattern)
建造器模式,是于创建带有大量参数的对象,并避免因参数数量多而产生的一些问题(如状态不一致-JavaBean的setter模式). 如果参数多且有些是必须初始化的,有些是不一定需要初始化的时候,创建对象 ...
- 设计模式学习--装饰者模式(Decorator Pattern)
概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...
- 大话设计模式--装饰者模式 Decorator -- C++实现实例
1.装饰者模式 Decorator 动态地给一个对象添加一个额外的职责, 就添加功能来说, 装饰模式比生成子类更为灵活. 每个装饰对象的实现和如何使用这个对象分离, 每个装饰对象只关心自己的功能,不 ...
- 23种设计模式之装饰器模式(Decorator Pattern)
装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包 ...
- 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...
- C#设计模式之装饰者模式(Decorator Pattern)
1.概述 装饰者模式,英文名叫做Decorator Pattern.装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 2 ...
随机推荐
- LAMP配置虚拟目录
1. httpd.conf中添加 Listen 81 2. 1 <VirtualHost 127.0.0.2:81> 2 DocumentRoot E:\ws\2011\DiscuzSp ...
- java多线程与单例模式(Singleton)不得不说的故事
转发自:http://blog.csdn.net/ligang7560/article/details/50890282 单例模式的多种实现方式 我们都知道单例模式有几种常用的写法: - 饿汉模式 - ...
- MVC 多语言记录1 设置默认的ResourceType
http://stackoverflow.com/questions/3260748/default-resource-for-data-annotations-in-asp-net-mvc Add ...
- Sql Server之旅——第十二站 sqltext的参数化处理
说到sql的参数化处理,我也是醉了,因为sql引擎真的是一个无比强大的系统,我们平时做系统的时候都会加上缓存,我想如果没有缓存,就不会有什么 大网站能跑的起来,而且大公司一般会在一个东西上做的比较用心 ...
- oracle--trunc与to_char的区别
trunc取得是天(可比较),而to_char取得是数值(可计算): 但trunc(date) 具有与to_char(date) 相似的功能,但有区别: trunc(sysdate,'cc') ...
- 关于Leetcode上二叉树的算法总结
二叉树,结构很简单,只是比单链表复杂了那么一丢丢而已.我们先来看看它们结点上的差异: /* 单链表的结构 */ struct SingleList{ int element; struct Singl ...
- hdu Dylans loves tree [LCA] (树链剖分)
Dylans loves tree view code#pragma comment(linker, "/STACK:1024000000,1024000000") #includ ...
- 支付宝APP支付开发- IOException : DerInputStream.getLength(): lengthTag=127, too big.
支付宝APP支付Java开发报错: IOException : DerInputStream.getLength(): lengthTag=127, too big. 后来排查是因为没有设置私钥.
- [转] cordova-plugin-x-toast
本文转自:https://www.npmjs.com/package/cordova-plugin-x-toast cordova plugin add https://github.com/Eddy ...
- [麦先生]TP3.2之微信开发那点事[基础篇](微信支付签名算法)
两种模式:扫码支付和微信内支付(调用js-sdk) trade_type==native即扫码支付,只需要将code_url转成二维码,使用微信扫码即可: js-sdk微信内支付-调用微信js-sdk ...