《Head First》第三节 装饰者模式

星巴兹咖啡通过装饰者模式解决了原有系统扩展性问题,实现了动态为对象添加职责的功能,提高了系统的灵活性。

背景介绍:星巴兹是一家很火爆的咖啡连锁店,因为扩张很快,需求多样化,原系统已不能满足。

原系统设计:


购买咖啡时,会要求加各种调料,系统要根据加的不同调料收取不同的费用,导致结构图如下:


解决方案:

以饮料为主体,然后运行时,以调料来“装饰”(decorate)饮料。

比如,顾客要加摩卡和奶泡的深焙咖啡。那么要做的是:

1.拿一个深焙咖啡(DarkRoast)对象

2.以摩卡(Mocha)对象装饰它

3.以奶泡(Whip)对象装饰它

4.调用cost()方法,并依赖委托(delegate)将调料的价钱加上去。

创建的图如下:


结算时,最外圈装饰者(Whip)的cost()就可以得到:


装饰者模式类图:


参照此类图,得到星巴兹饮料类图:


具体实现代码:

Beverage(饮料)

public abstract class Beverage {
    public String description = "Unknown Beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();
}

装饰者类,Condiment(调料)

public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}


各种饮料

HouseBlend(综合咖啡)
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "HouseBlend";
    }

    public double cost() {
        return .89;
    }
}
Espresso(浓缩咖啡)
public class Espresso extends Beverage {
    public Espresso() {
        description = "Espresso";
    }

    public double cost() {
        return 1.99;
    }
}
Decaf(低咖啡因)
public class Decaf extends Beverage {
    public Decaf() {
        description = "Decaf";
    }

    public double cost() {
        return 1.05;
    }
}
DarkRoast(深焙咖啡)
public class DarkRoast extends Beverage {
    public DarkRoast() {
        description = "DarkRoast";
    }

    public double cost() {
        return .99;
    }
}

各种调料

Mocha(摩卡)
public class Mocha extends CondimentDecorator {
    Beverage beverage;

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

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

    public double cost() {
        return beverage.cost() + .20;
    }
}
Soy(豆浆)
public class Soy extends CondimentDecorator {
    Beverage beverage;

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

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

    public double cost() {
        return beverage.cost() + .30;
    }
}
Whip(牛奶)
public class Whip extends CondimentDecorator {
    Beverage beverage;

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

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

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

测试:

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());
        Beverage beverage1 = new Mocha(new Mocha(new Whip(new DarkRoast())));
        System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
        Beverage beverage2 = new Soy(new Mocha(new Whip(new DarkRoast())));
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    }
}

运行结果:



Java I/O流中的装饰者模式


编写自己的I/O装饰者,实现大小写转换

public class LowerCaseInputStream extends FilterInputStream {
    public LowerCaseInputStream(InputStream in) {
        super(in);
    }

    public int read() throws IOException {
        int c = super.read();
        return (c == -1 ? c : Character.toLowerCase((char)c));
    }

    public int read(byte b[], int off, int len) throws IOException {
        int result = super.read(b, off, len);
        for (int i = off; i < off + result; i++) {
            b[i] = (byte) Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}

测试

public class InputTest {
    public static void main(String[] args) {
        int c;
        try {
            InputStream is = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
            while ((c = is.read()) >= 0) {
                System.out.print((char)c);
            }
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果


总结:

装饰者模式--动态的将责任附加到对象上,想要扩展功能,装饰者提供有别于继承的另一种选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值