您的位置:首页 > 编程语言 > Java开发

Java装饰者模式

2015-11-24 12:52 423 查看


Hello,即将要写的这篇文章,是对刚刚学习完的装饰者模式的一个总结啦,也不是什么技术难点,就是巩固一下啦。





一.装饰者模式的定义
装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
只看定义真的有些不明白,先简单说明一下,下面还有例子呢。

(1)定义中提到了继承,看来装饰者模式是来解决扩展功能时使用继承的不足的;
(2)可以做到运行时装饰类,给对象赋予新的职责。
(3)还是看下面的例子吧。

二.实例--饮品店
饮品店里有,饮品--咖啡、果汁、茶类,饮品中可以加不同的配料--摩卡、牛奶、糖、奶泡;不同的饮品加上不同的配料有不同的价钱,怎样实现呢?
方式一:单纯的继承
最突出的缺点--造成类爆炸(组合的种类太多);
方式二:使用装饰者模式
1.装饰者模式的组成:抽象组件(Beverage)、具体组件(Coffee、Tea等)、抽象装饰者(IngredientDecorator)、具体装饰者(Mocha、Milk等),以例子说明的关系图如下:



2.代码示例:
抽象组件--超类--Beverage:

public abstract class Beverage {
//description实例变量表示不同的描述,由子类赋值使用
String description = "Uknown Beverage";

public String getDescription() {
return description;
}

//抽象方法,由子类实现
public abstract double cost();
}
具体组件--B_Coffee、B_FruitJuice等:
public class B_Coffee extends Beverage{

/**
* 在构造器中设置饮料的描述
*/
public B_Coffee(){
description = Description.COFFEE;
}

/**
* 实现父类--抽象组件中的抽象方法
* 计算该饮料的价钱
*/
public double cost() {
return Cost.COFFEE;
}

}
public class B_FruitJuice extends Beverage{
public B_FruitJuice(){
description = Description.FRUIT_JUICE;
}

public double cost() {
return Cost.FRUIT_JUICE;
}

}
抽象装饰者--IngredientDecorator:
/**
* 继承的目的是为了IngredientDecorator能够取代Beverage
* @author wangzhaoli
*
*/
public abstract class IngredientDecorator extends Beverage{
/**
* IngredientDecorator中覆盖父类中的getDescription()方法
* 继承IngredientDecorator的所有观察者需各自实现
*/
public abstract String getDescription();
}
具体装饰者们--C_Mocha、C_Milk等:
/**
* C_Mocha是一个装饰者
* C_Mocha继承的CondimentDecorator
* CondimentDecorator继承了Beverage
* @author wangzhaoli
*
*/
public class C_Mocha extends IngredientDecorator{

/**
* 要让C_Mocha能够引用一个Beverage,做法是:
* 1.用一个实例变量记录Beverage,也就是被装饰者;
* 2.想办法让Beverage被记录到实例变量中,即构造器参数实例化。
*/
private Beverage beverage;

public C_Mocha(Beverage beverage){
this.beverage = beverage;
}

/**
* 实现父类CondimentDecorator中的抽象方法
*/
public String getDescription() {
//利用委托的方法得到之前的描述
return beverage.getDescription() + "," + Description.MOCHA;
}

/**
* 实现父类的父类Beverage中的抽象方法
*/
public double cost() {
return beverage.cost() + Cost.MOCHA;
}

}
public class C_Milk  extends IngredientDecorator{

private Beverage beverage;

public C_Milk(Beverage beverage){
this.beverage = beverage;
}

public String getDescription() {
return beverage.getDescription() + "," + Description.MILK;
}

public double cost() {
return beverage.cost() + Cost.MILK;
}

}
测试类--main:
public class MainTest {
public static void main(String[] args) {
Beverage fruitJuice = new B_FruitJuice();
System.out.println(fruitJuice.getDescription()+":"+fruitJuice.cost());
System.out.println();

Beverage coffee = new B_Coffee();
coffee = new C_Mocha(new C_Mocha(new C_Suger(coffee)));
System.out.println(coffee.getDescription()+":"+coffee.cost());
System.out.println();

Beverage tea = new B_Tea();
tea = new C_Mocha(tea);
tea = new C_Milk(tea);
tea = new C_Suger(tea);
tea = new C_Form(tea);
System.out.println(tea.getDescription()+":"+tea.cost());
System.out.println();
}

}
测试结果:
Fruit Juice:8.0

Coffee,Suger,Mocha,Mocha:9.5

Tea,Mocha,Milk,Suger,Form:9.5
二.由实例说明装饰者模式

1.装饰者模式中很好的体现了组合(composition)和委托(delegation):
(1)利用继承设计子类的行为是在编译时静态决定的,利用组合的做法扩展对象的行为可以在运 行时动态的进行扩展;
(2)利用继承达到"类型匹配",而不是获得"行为",新的行为是由"组合对象"得来的;
(3)利用组合和委托可以实现在运行时具有继承的效果;
2.装饰者模式完全遵循"开放--关闭原则":类应该对扩展开放,对修改关闭。
3.以例子说明装饰者的使用:
拿一个咖啡对象,用摩卡装饰它,再用牛奶装饰它,然后调用cost()方法,并依赖委托 (delegate)将各种配料的价格加上去。
4.每个具体的组件都可以单独使用,或者被装饰者包装起来动态的加上新行为使用;
5.装饰者与抽象组件是"有一个"的关系,所以需要在每一个具体装饰者中定义一个实例变量以保存
某个具体组件的引用;
6.装饰者的新行为是指:通过在旧行为前面/后面加上一些计算、拼接等处理;
7.装饰者和被装饰者对象有相同的超类型;
8.可以用一个或多个装饰者包装一个对象;
9.装饰者可以所委托被装饰者的行为之前/之后,加上自己的行为,以达到指定的目的;
本文出自 “MySpace” 博客,请务必保留此出处http://wangzhaoli.blog.51cto.com/7607113/1716319
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: