设计模式之装饰者模式(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gacmy/article/details/50784714

设计模式之装饰者模式一
一个咖啡店的咖啡为一个抽象类,所有其它的咖啡类型都继承这个类,
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.99espresso1.99
espresso,Mocha,Mocha,Whip $2.79

没有更多推荐了,返回首页