设计模式之装饰者模式一
一个咖啡店的咖啡为一个抽象类,所有其它的咖啡类型都继承这个类,
Breverage
String description
getDescription()
Cost()
getDescription返回饮料的名称
Cost是一个抽象的方法,子类中实现自己的cost方法。
下面有几个饮料
HouseBlend DarkRost Decaf Espresso 这些类都必须实现自己的cost方法。
现在各种咖啡可以加入不同的调料,例如 蒸奶steamed milk 豆浆soy 摩卡mocha
不同的调料需要不同的价格 所以子类的咖啡必须考虑到这些调料
第一种尝试:
HouseBlendWithSteamedMilkAndMocha
DarkRostWithMocha
DecafWithSoy…
这样就会有n种类,这种实现方式会使子类太多难以维护。
如果牛奶的价格上涨的话需要将所有有关牛奶的类的价格改动一下。
这样的方法太笨了,可以把调料作为饮料类的成员变量
Beverage
Beverage的成员变量Field
Milk
Soy
Mocha
Whip
Method:
getDescription()
Public double Cost(){
Double total = 0.0;
If(hasMilk()){
Total+=milkCost;
}
If(hasSoy()){
Total+=soyCost;
}
…
Return total;
}
hasMilk()
setMilk()
hasSoy()
setSoy()
…
使用has set方法设置调料的布尔值 和获得调料的布尔值,
DarkRostWithMochaWithSoy类cost方法只需要这样实现:
DarkRost extends Breverage{
Public DarkRost(){
Decsription= darkrost
}
Public double cost(){
Return Super.cost()+1.99;
}
}
现在这个设计只需要五个类,但是有些业务需求可能影响现在的设计.
调料价钱改变我们需要改变现有代码,
出现新的调料,需要改变超类的cost方法,加上has..新方法。
可能开发出新的饮料,例如茶tea hasMilk 这样的方法将不合适,
如果顾客要双倍mocha 没有办法处理。
下面有一些概念:
利用组合composition 和委托delegation 可以在运行时具有继承行为的效果。
利用继承设计子类的行为,时在编译时静态决定,所有子类都会继承到相同的行为。利用组合扩展对象的行为,就可以在运行时动态的进行扩展。
通过动的组合对象,可以写新的代码添加新的功能,不需要修改现有代码。
一条新的设计原则产生:
类应该对扩展开放,对修改关闭。
下面利用装饰者模式重新设计系统:
拿一个DarkRoast对象
我们以mocha对象装饰它
以whip对象装饰它
调用cost方法,依赖委托将调料价格加上去.
Mocha对象包裹DarkRoast对象,whip对象包裹mocha对象,只需要调用whip的cost方法就可以获得这一种饮料的价钱了。
装饰者模式: 动态将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者类图如下:
Compoent
ConcreteComponent继承Component
Dcorator继承Component 也是一个抽象类
ConcreteDecoratorA extends Decorator
ConcreteDecoratorB extends Dcorator
继承component的组件可以单独使用,或者被装饰者包起来使用。
每个装饰者类里面都有一个component 实例变量 保存component引用。
下面利用装饰者模式设计新的系统:
Beverage
Field:
Description
Method:
getDescription()
Cost()
HouseBlend extends Beverage method:cost()
DarkRoast extends Beverage method:cost()
…
CondimentDecorator extends Beverage method:getDescription()
Milk extends CondimentDecorator filed: Beverage method: cost() getDescription()
…
下面为详细代码:
饮料类:
//饮料类
public abstract class Beverage {
String description = “Unknown Beverage”;
public String getDescription(){
return description;
}
public abstract double cost();
}
//调料类
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
具体的饮料类:
package com.gac.zsz;
public class Espresso extends Beverage{
public Espresso(){
description = "espresso";
}
@Override
public double cost() {
// TODO Auto-generated method stub
return 1.99;
}
}
具体的调料类:
package com.gac.zsz;
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage bevrage){
this.beverage = bevrage;
}
@Override
public double cost() {
// TODO Auto-generated method stub
return 0.20+beverage.cost();
}
@Override
public String getDescription() {
return this.beverage.getDescription()+",Mocha";
}
}
package com.gac.zsz;
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage bevrage){
this.beverage = bevrage;
}
@Override
public double cost() {
// TODO Auto-generated method stub
return 0.40+beverage.cost();
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription()+",Whip";
}
}
测试类:
package com.gac.zsz;
public class Test {
public static void main(String[] args){
Beverage beverage = new Espresso();
print(beverage.getDescription()+”
”+beverage.cost());//Beverageb1=newEspresso();print(b1.getDescription()+”
”+b1.cost());
b1 = new Mocha(b1);
b1 = new Mocha(b1);
b1 = new Whip(b1);
print(b1.getDescription()+" $"+b1.cost());
}
public static void print(String str){
System.out.println(str);
}
}
//运行结果:
espresso
1.99espresso
1.99
espresso,Mocha,Mocha,Whip $2.79