1.什么是装饰模式
装饰器模式,也称为包装模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能。其结构图如下:
Component为统一接口,也是装饰类和被装饰类的基本类型。
ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。
2.代码实现
首先定义一个统一的接口House
。
package com.designpattern.decorate;
/**
* @description: 房屋基础接口
* @author: Codegitz
* @create: 2020-05-19 15:07
**/
public interface House {
void build();
}
HouseImpl
实现统一接口,HouseImpl
是一个完整的类。
package com.designpattern.decorate;
/**
* @description: 房屋基类实现类
* @author: Codegitz
* @create: 2020-05-19 15:37
**/
public class HouseImpl implements House {
@Override
public void build() {
System.out.println("start build....");
}
}
package com.designpattern.decorate;
/**
* @description: 房屋装饰类
* @author: Codegitz
* @create: 2020-05-19 15:18
**/
public class HouseDecorate implements House{
private House house;
public HouseDecorate(House house){
this.house = house;
}
@Override
public void build() {
house.build();
}
}
package com.designpattern.decorate;
/**
* @description: 房屋装饰类具体实现类
* @author: Codegitz
* @create: 2020-05-19 15:36
**/
public class HouseDecorateImpl1 extends HouseDecorate {
public HouseDecorateImpl1(House house) {
super(house);
}
@Override
public void build() {
super.build();
System.out.println("HouseDecorateImpl1 do something...");
}
}
package com.designpattern.decorate;
/**
* @description: 测试类
* @author: Codegitz
* @create: 2020-05-19 15:38
**/
public class Test {
public static void main(String[] args) {
House house = new HouseImpl();
System.out.println("======without decorate======");
house.build();
HouseDecorate houseDecorate1 = new HouseDecorateImpl1(house);
HouseDecorate houseDecorate2 = new HouseDecorateImpl2(house);
System.out.println("=====HouseDecorateImpl1 decorate====");
houseDecorate1.build();
System.out.println("=====HouseDecorateImpl2 decorate====");
houseDecorate2.build();
}
}
运行结果如下:
======without decorate======
start build....
=====HouseDecorateImpl1 decorate====
start build....
HouseDecorateImpl1 do something...
=====HouseDecorateImpl2 decorate====
start build....
HouseDecorateImpl2 do something...
附完整代码,需要自取,顺便点个star。
3.装饰与代理区别
装饰模式和代理模式思路和实现都非常相似,那么两者真正的区别是什么。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。当我们使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
4.装饰模式应用场景
在IO中,具体构件角色是节点流,装饰角色是过滤流。
FilterInputStream
和FilterOutputStream
是装饰角色,而其他派生自它们的类则是具体装饰角色。
DataOutputStream out=new DataOutputStream(new FileOutputStream());
这就是装饰者模式,DataOutputStream
是装饰者子类,FileOutputStream
是实现接口的子类。
这里不会调用到装饰者类--FilterOutputStream
,只是作为继承的另一种方案,对客户端来说是透明的,是为了功能的扩展。