Decorator - 装饰者模式

Decorator-装饰者模式

Why 不改变原有对象结构, 为其增加一些额外功能
角色
角色 作用
Component(抽象构件) 定义核心对象的接口
ConcreteComponent(具体构件) 核心对象,实现接口的核心功能
Decorator(装饰抽象类) 内置 Component 对象,实现 Component 接口,同时提供额外功能接口
ConcreteDecorator(具体装饰类) 扩展装饰抽象类,实现具体功能增强

How

继承又聚合

image1

通俗的说:

就是 抽象装饰继承or实现抽象组件,重写其方法,

(必须添加一个形参为抽象组件的构造方法)

然后具体装饰同样有形参为抽象组件的构造方法,

但是调用的是super(抽象组件)这个构造方法

并且在每一个方法中都是调用super+该装饰的逻辑

// 抽象组件

1
2
3
4
<p>interface Coffee {</p>
<p>double cost();</p>
<p>String info();</p>
<p>}</p>

// 具体组件

1
2
3
4
<p>class SimpleCoffee implements Coffee {</p>
<p>public double cost() { return 5; }</p>
<p>public String info() { return "普通咖啡"; }</p>
<p>}</p>

// 装饰抽象类

1
2
3
4
5
6
<p>abstract class CoffeeDecorator implements Coffee {</p>
<p><span style='background:yellow;mso-highlight:yellow'>protected Coffee coffee;</span></p>
<p><span style='background:yellow;mso-highlight:yellow'> public CoffeeDecorator(Coffee coffee) { this.coffee = coffee; }</span></p>
<p>public double cost() { return coffee.cost(); }</p>
<p>public String info() { return coffee.info(); }</p>
<p>}</p>

// 具体装饰

1
2
3
4
5
<p>class MilkDecorator extends CoffeeDecorator {</p>
<p>public MilkDecorator(Coffee coffee) { <span style='background:yellow;mso-highlight:yellow'>super(coffee);</span> }</p>
<p>public double cost() {<span style='background:yellow;mso-highlight:yellow'> return super.cost() + 2;</span> }</p>
<p>public String info() { <span style='background:yellow;mso-highlight:yellow'>return super.info() + " + 牛奶";</span> }</p>
<p>}</p>

1
2
3
4
5
<p>class SugarDecorator extends CoffeeDecorator {</p>
<p>public SugarDecorator(Coffee coffee) { super(coffee); }</p>
<p>public double cost() { return super.cost() + 1; }</p>
<p>public String info() { return super.info() + " + 糖"; }</p>
<p>}</p>

// 测试

1
2
3
4
5
6
7
8
<p>public class Demo {</p>
<p>public static void main(String[] args) {</p>
<p>Coffee coffee = new SimpleCoffee();</p>
<p>coffee = new MilkDecorator(coffee);</p>
<p>coffee = new SugarDecorator(coffee);</p>
<p>System.out.println(coffee.info() + " = " + coffee.cost());</p>
<p>}</p>
<p>}</p></td>
使用场景

image2

Jdk源码

1.FileInputStream

image3

静态代理和装饰者模式的区别

image4