设计模式(三)The Decorator Pattern 装饰器模式
来源:互联网 发布:360恢复软件免费版 编辑:程序博客网 时间:2024/05/16 08:26
问题引入
实现在一份咖啡中加入摩卡(Mocha),再加上奶泡(Whip),并且计算咖啡总共的价钱。
模式定义
动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
认识模式
在被装饰者的前面或者后面加上附加的一些行为,从而扩展被装饰者的功能,接口没变,但是增强了性能。
问题解决
使用继承同一父类或者实现相同的接口,使装饰者和被装饰者具有相同的类型,从而实现多重的装饰效果!
直接上代码
1>Beverage饮料类,所有的类都继承自它,从而具有相同的类型
package
my.oschina.net.design.decorator;
public
abstract
class
Beverage {
String description =
""
;
public
String getDescription()
{
return
description;
}
public
abstract
double
cost();
}
2>Coffe类(被装饰者)
package
my.oschina.net.design.decorator;
/**
* 纯coffe每份0.9元
* @author Eswin
*
*/
public
class
Coffe
extends
Beverage{
public
Coffe()
{
description =
"coffe"
;
}
@Override
public
double
cost() {
// TODO Auto-generated method stub
return
0.9
;
}
}
3>第一个装饰者(说实话它也是被装饰者,因为它还是会被另外的装饰者装饰)
package
my.oschina.net.design.decorator;
/**
* Mocha每份0.5元
* @author Eswin
*
*/
public
class
Mocha
extends
Beverage{
Beverage beverage;
public
Mocha(Beverage beverage)
{
this
.beverage = beverage;
}
public
String getDescription()
{
return
beverage.getDescription() +
" + Mocha"
;
}
@Override
public
double
cost() {
// TODO Auto-generated method stub
return
beverage.cost() +
0.5
;
}
}
4>第二个装饰者(它也是被装饰者,因为它还是会被另外的装饰者装饰)
package
my.oschina.net.design.decorator;
/**
* Whip每份1.0元
* @author Eswin
*
*/
public
class
Whip
extends
Beverage{
Beverage beverage;
public
String getDescription()
{
return
beverage.getDescription() +
" + Whip"
;
}
public
Whip(Beverage beverage)
{
this
.beverage = beverage;
}
@Override
public
double
cost() {
// TODO Auto-generated method stub
return
beverage.cost() +
1.0
;
}
}
5>Test一下
package
my.oschina.net.design.decorator;
public
class
TestDecorator {
public
static
void
printCoffe(Beverage beverage)
{
System.out.println(
"Coffe==>"
+ beverage.getDescription());
System.out.println(
"Coffe_Price==>"
+ beverage.cost());
}
public
static
void
main(String[] args)
{
System.out.println(
"纯Coffe"
);
Beverage beverage =
new
Coffe();
printCoffe( beverage);
System.out.println(
"Coffee加上一份Mocha"
);
beverage =
new
Mocha(beverage);
printCoffe( beverage);
System.out.println(
"Coffee加上两份Mocha"
);
beverage =
new
Mocha(beverage);
printCoffe( beverage);
System.out.println(
"再加上一份Whip"
);
beverage =
new
Whip(beverage);
printCoffe( beverage);
}
}
模式延伸
你想起了java中各种各样的I/O流了吗?仔细想想,是不是用到了装饰器模式?
模式要点
1、继承同一父类或者实现相同的接口,从而使装饰者与被装饰者具有相同的类型;
2、在装饰者中保存被装饰着对象的引用,然后在装饰者方法的前后加上代码扩展功能。
问题引入
咖啡店的类设计:
一个饮料基类,各种饮料类继承这个基类,并且计算各自的价钱。
饮料中需要加入各种调料,考虑在基类中加入一些布尔值变量代表是否加入各种调料,基类的cost()中的计算各种调料的价钱,子类覆盖cost(),并且在其中调用超类的cost(),加上特定饮料的价钱,计算出子类特定饮料的价钱。
缺点:类数量爆炸、基类加入的新功能并不适用于所有的子类、调料价钱的改变、新调料的出现都会要求改变现有代码;有的子类并不适合某些调料等情况……
设计原则
类应该对扩展开放,对修改关闭。
我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。
如能实现这样的目标,有什么好处呢?这样的设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求。
要让OO设计同时具备开放性和关闭性,不是一件容易的事,通常来说,没有必要把设计的每个部分都这么设计。
遵循开放-关闭原则,通常会引入新的抽象层次,增加代码的复杂度。
我们需要把注意力集中在设计中最有可能改变的地方,然后应用开放-关闭原则。
用装饰者模式解决问题
解决咖啡店饮料问题的方法:
以饮料为主体,然后在运行时以调料来“装饰”饮料。
比如,顾客想要摩卡(Mocha)和奶泡(Whip)深焙咖啡(DarkRoast):
DarkRoast继承自Beverage,有一个cost()方法。
第一步,以DarkRoast对象开始;
第二步,顾客想要摩卡,所以建立一个Mocha装饰者对象,并用它将DarkRoast对象包装(wrap)起来;
第三步,顾客想要奶泡,所以建立一个Whip装饰者对象,并用它将Mocha对象包起来;(Mocha和Whip也继承自Beverage,有一个cost()方法);
最后,为顾客算钱,通过调用最外圈装饰者(Whip)的cost()就可以。Whip()的cost()会先委托它装饰的对象(Mocha)计算出价钱,然后在加上奶泡的价钱。Mocha的cost()也是类似。
装饰者模式的特点
装饰者和被装饰对象有相同的超类型。
可以用一个或多个装饰者包装一个对象。
因为装饰者和被装饰者具有相同的类型,所以任何需要原始对象的场合,可以用装饰过的对象代替。
装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
装饰者模式的定义
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式的实现
实现类图如下:
装饰者和被装饰者具有共同的超类,利用继承达到“类型匹配”,而不是利用继承获得“行为”;将装饰者和被装饰者组合时,加入新的行为。
解决本文中饮料的具体问题时,图中Component即为Beverage(可以是抽象类或者接口),而ConcreteComponent为各种饮料,Decorator(抽象装饰者)为调料的抽象类或接口,ConcreteDecoratorX则为各种具体的调料。
因为使用对象组合,可以把饮料和调料更有弹性地加以混合与匹配。
代码外部细节:
代码中实现的时候,通过构造函数将被装饰者传入装饰者中即可,如最后的调用形式如下:
Beverage beverage = new DarkRoast();
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
即完成了两层包装,此时再调用beverage的cost()函数即可得到总价。
java.io包内的装饰者模式
装饰者模式的缺点:在设计中加入大量的小类,如果过度使用,会让程序变得复杂。
- 设计模式(三)The Decorator Pattern 装饰器模式
- 设计模式2--装饰模式(the decorator design pattern)
- 设计模式系列(三)装饰者模式(Decorator Pattern)
- 设计模式-装饰模式(Decorator Pattern)
- 7.5.1.2 装饰设计模式(THE DECORATOR DESIGN PATTERN)
- 设计模式 —— 装饰器模式(Decorator Pattern)
- 【设计模式】装饰器模式(Decorator Pattern)
- 装饰者模式(the Decorator Pattern)
- 三、装饰模式(Decorator Pattern)
- 装饰设计模式(decorator design pattern)
- 设计模式[6] Decorator Pattern 装饰模式
- 设计模式-装饰者模式(Decorator Pattern)
- 设计模式之装饰模式(Decorator Pattern)
- 设计模式心得:装饰模式 (decorator pattern)
- 设计模式-装饰模式(Decorator Pattern)
- 设计模式之装饰模式--- Pattern Decorator
- 设计模式_装饰模式(Decorator Pattern)
- 设计模式【装饰模式Decorator Pattern】
- Merge Sorted Array,Merge Two Sorted Lists,Remove ... Sorted List,Count and Say,Climbing Stairs
- zoj3822(概率DP)
- Sizeof与Strlen的区别与联系
- ClassLoader.getResourceAsStream() 与 Class.getResourceAsStream()的区别
- [玩树莓派系列]树莓派实现家庭监控
- 设计模式(三)The Decorator Pattern 装饰器模式
- 网站搭建从零开始(五) WordPress的安装
- 【OJ】贪心——区间问题 hzu.acmclub.com 1126看电视
- Atititjs javascript异常处理机制与java异常的转换.js exception process
- mysql的一些学习笔记。
- cocos2d x 3.3.0中CCScale9Sprite类
- Leetcode - Best Time to Buy and Sell Stock
- .atitit.web 推送实现解决方案集合(3)----dwr3 Reverse Ajax
- 『ANDROID』去除或替换listview 默认的点击选中时的颜色