概述
装饰器模式是结构性模式之一,很多人容易把装饰器模式和适配器模式搞混,本次分享的是装饰器模式,后面会分享适配模式,然后就很清楚的区别他们两各自的特性了。
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
特点
动态添加或者覆盖被装饰的接口/抽象类行为。
关系
装饰者和被装饰者有着接口/抽象类层次关系。
自写案例
/**
* 抽象构建角色
*
* @author tianwc
* @date 2018/11/20
*/
public interface PayService {
/**
* 支付
*/
void pay();
}
/**
* 具体构建角色
*
* @author tianwc
* @date 2018/11/20
*/
public class PayServiceImpl implements PayService {
@Override
public void pay() {
System.out.println("执行PayServiceImpl--的--支付--支付方法");
}
}
/**
* 装饰角色
*
* @author tianwc
* @date 2018/11/20
*/
public interface PayMsgService extends PayService {
/**
* 支付
*/
@Override
void pay();
/**
* 发站内信
*/
void sendMsg();
}
/**
* 装饰角色 增加了sendMsg
*
* @author tianwc
* @date 2018/11/20
*/
public class PayMsgServiceImpl implements PayMsgService {
private PayService payService;
public PayMsgServiceImpl(PayService payService) {
this.payService = payService;
}
/**
* 交易
*/
@Override
public void pay() {
System.out.println("开始交易");
payService.pay();
sendMsg();
System.out.println("交易完成");
}
/**
* 发送站内信
*/
@Override
public void sendMsg() {
System.out.println("发送站内信");
}
}
/**
* 装饰模式demo测试类
*
* @author tianwc
* @date 2018/11/20
*/
public class DecoratorDemo {
public static void main(String[] args) {
PayService payService = new PayServiceImpl();
PayService payService2 = new PayMsgServiceImpl(payService);
payService2.pay();
}
}
原有功能只是支付功能,现在我在这基础之上添加了一个功能发送站内信(用户在自己消息里能看到的交易信息)。以前的代码是完全没有动的。这样就咱们就把装饰模式给用起来了。
大佬们应用
装饰模式在Java I/O的应用
import java.io.DataInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;
/**
* 装饰器适配模式demo
*
* @author tianwc
* @date 2017/11/18
*/
public class DecoratorDemo {
public static void main(String[] args) {
/**
* 这个怎么获取的咱们不关心,(被装饰者)
*/
InputStream inputStream = null;
/**
* 装饰者
* FilterInputStream的构造方法是protected,所以这里就不能new了,
* DataInputStream是FilterInputStream的子类,并且构造函数是public
*
*/
// FilterInputStream fileInputStream=new FilterInputStream(inputStream);
FilterInputStream fileInputStream = new DataInputStream(inputStream);
}
}
咱们看看他们的关系
InputStream是顶层抽象类
public abstract class InputStream implements Closeable {
FilterInputStream
从上面代码可以看得出来FilterInputStream是InpoutStream的子类,并且还有个构造函数其入参是InputStream。
因为FilterInpoutStream中的构造方法是protected修饰的,所以上面的new对象的时候就得借助于其子类DataIputStream。上面可以看出构造方法入参都是父类接口。
装饰模式在dubbo中的应用
ProtocolFilterWrapper的构造方法入参为它的Protocol接口类这也是装饰模式的应用之一。
优缺点
优点
- 与继承关系目的都是要扩展对象的功能,但装饰模式可以提供比继承更多的灵活性,装饰模式允许系统动态的决定贴上一个需要的装饰,或者除掉一个不需要的装饰。继承关系则不同,继承关系是静态的,他在系统运行前就已经决定了。
- 通过使用不同的具体修饰类及这些装饰类的排列组合,设计师可以创造出很多不同的行为组合。而继承没有这个关系优势。每一种不同的组合均需要事先通过子类继承的方式设计好。
- 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加容易出错
缺点
- 使用装饰模式会产生比使用继承关系更多的类。特别是这些类看上去都比较相近