hooyantsing's Blog

P73 装饰者模式(3)-工作原理

字数统计: 627阅读时长: 3 min
2020/11/10

尚硅谷Java设计模式(图解+框架源码剖析)

装饰者模式

动态的将新功能附加到对象上。在对象扩展方面,它比继承更有弹性,装饰者模式以体现了开闭原则。

hooy.xyz

星巴克案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classDiagram
class Drink{
<<abstract>>
}
class Coffee
class LongCoffee
class Espresso
class Decorator
class Chocolate
class Milk
Drink <|-- Coffee
Drink <|-- Decorator
Decorator o-- Coffee
Coffee <|-- LongCoffee
Coffee <|-- Espresso
Decorator <|-- Chocolate
Decorator <|-- Milk

总基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package xyz.hooy.decorator;

public abstract class Drink {
private String des;
private float price = 0.0f;

public String getDes() {
return des;
}

public void setDes(String des) {
this.des = des;
}

public float getPrice() {
return price;
}

public void setPrice(float price) {
this.price = price;
}

// 计算全部费用的抽象方法
// 子类实现
public abstract float cost();
}

单品基类

1
2
3
4
5
6
7
8
// 单品
public class Coffee extends Drink {
// 单品咖啡,全部费用就是它本身价格
@Override
public float cost() {
return super.getPrice();
}
}

单品A

1
2
3
4
5
6
public class LongCoffee extends Coffee {
public LongCoffee(){
super.setDes("美式咖啡");
super.setPrice(2.0f);
}
}

单品B

1
2
3
4
5
6
public class Espresso extends Coffee {
public Espresso(){
super.setDes("意大利咖啡");
super.setPrice(3.0f);
}
}

调味品基类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 调味品
public class Decorator extends Drink{
private Drink drink;

public Decorator(Drink drink){
this.drink = drink;
}

@Override
public float cost() {
// 调料价格 + 单品咖啡
return super.getPrice() + drink.cost();
}

@Override
public String getDes() {
return super.getDes() + "/" + super.getPrice() + " && " + drink.getDes();
}
}

调味品A

1
2
3
4
5
6
7
public class Chocolate extends Decorator {
public Chocolate(Drink drink) {
super(drink);
super.setDes("巧克力");
super.setPrice(4.0f);
}
}

调味品B

1
2
3
4
5
6
7
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
super.setDes("牛奶");
super.setPrice(1.0f);
}
}

装饰模式调用者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {
public static void main(String[] args) {
// 首先,创建单品
Drink drink = new LongCoffee();
System.out.println("总价格:" + drink.cost());
System.out.println("账单:" + drink.getDes());
drink = new Milk(drink);
System.out.println("总价格:" + drink.cost());
System.out.println("账单:" + drink.getDes());
drink = new Chocolate(drink);
System.out.println("总价格:" + drink.cost());
System.out.println("账单:" + drink.getDes());
}
}

执行结果:

总价格:2.0
账单:美式咖啡
总价格:3.0
账单:牛奶/1.0 && 美式咖啡
总价格:7.0
账单:巧克力/4.0 && 牛奶/1.0 && 美式咖啡

装饰者模式在JDK IO中的应用

hooy.xyz

  1. InputStream 是抽象类,类似我们前面讲的 Drink
  2. FileInputStream 是 InputStream 子类,类似我们前面的 LongCoffee 、Espresso
  3. FilterInputStream 是 InputStream 子类,类似我们前面的 Decorator 修饰者
  4. DataInputStream 是 FilterInputStream 子类,具体的修饰者,类似前面的 Milk
  5. FilterInputStream 类有 protected volatile InputStream in; 即含被装饰者
CATALOG
  1. 1. 装饰者模式
    1. 1.1. 星巴克案例
  2. 2. 装饰者模式在JDK IO中的应用