1、一个实例
在一家咖啡店有很多种咖啡,但都基于一种基本饮料开发出来的,每一种咖啡也可以加入很多不同的配料。
饮料有:HouseBlend(首选咖啡),Espresso(浓缩咖啡),DarkRoast(焦炒咖啡),Decaf(脱因咖啡)
调料有:Milk(牛奶)、摩卡(mocha)、豆浆(Soy)、奶泡(Whip)
这时候用户下单要打印票据显示配方和价格,该如何做呢?
//被装饰者父类
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
//创建几个实现类
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
public class DarkRoast extends Beverage {
public Espresso() {
description = "DarkRoast";
}
@Override
public double cost() {
return 1.99;
}
}
- 装饰类(写法1)
//创建装饰者
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
// 创建具体的装饰者
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.2 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Mocha";
}
}
public class Milk extends CondimentDecorator {
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.1 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Milk";
}
}
- 装饰类(写法2)
//创建装饰者父类
public abstract class CondimentDecorator extends Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
public abstract String getDescription();
}
// 创建具体的装饰者
public class Mocha extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return 0.2 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Mocha";
}
}
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return 0.1 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Milk";
}
}
- main方法
public class StartbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new DarkRoast();
//一杯不加调料的咖啡
System.out.println(beverage.getDescription() + ",价格:" + beverage.cost());
//用摩卡和牛奶装饰下
Beverage beverage2 = new DarkRoast();
beverage2=new Mocha(beverage2);
beverage2=new Milk(beverage2);
System.out.println(beverage2.getDescription() + ",价格:" + beverage2.cost());
Beverage beverage3=new Milk(new Mocha(new DarkRoast()));
System.out.println(beverage3.getDescription() + ",价格:" + beverage3.cost());
}
}
输出
DarkRoast,价格:1.99
DarkRoast,Mocha,Milk,价格:2.29
DarkRoast,Mocha,Milk,价格:2.29
2、什么是装饰者模式
2.1、定义装饰者模式
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更具有弹性的替代方案。
2.2 特征
- 装饰者和被装饰者有相同的超类型。
- 可以用一个或多个装饰者包装一个对象。
- 对象可以在任何时候被装饰
怎么看出来是使用了装饰模式呢?
当你看到 new BufferedInputStream(new FileInputStream("test.txt"));这种写法就差不多了。
- 装饰者和被装饰者有相同的超类型
- 装饰者持有超类型的引用,这样装饰者就可以不断的修饰 被装饰者
3、 java中的实例
上图是java中的inputStream。我们可以看出来FilterInputStream就是我们的装饰者。
//被装饰者父类
public abstract class InputStream{
public abstract int read() ;
}
//实现类(具体被装饰者)
public class FileInputStream extends InputStream{
public FileInputStream(File file){}
public int read() throws IOException{}
}
public class StringBufferInputStream extends InputStream {
public synchronized int read(){}
public StringBufferInputStream(String s) { }
}
public class ByteArrayInputStream extends InputStream {
public ByteArrayInputStream(byte buf[]) {}
public synchronized int read(){}
}
- 装饰类
//创建装饰者
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
}
// 创建具体的装饰者
public class BufferedInputStream extends FilterInputStream {
public synchronized int read(){}
}
- 具体使用
public static void main(String[] args){
InputStream in = new BufferedInputStream(new FileInputStream("test.txt"));
}