基本设计原则中,有一条重要的设计准则: 合成/聚合复用原则。
代码复用应该尽可能使用委托,而不使用继承。因为,继承是一种紧密耦合,任何父类的改动都会影响其子类,不利于系统的维护;而委托则是松散耦合,只要接口不变,委托类的改动并不会影响其上层对象。
装饰者模式可以有效分离性能组件和功能组件,从而提升模块的可维护性,并增加模块的复用性。
装饰者模式的核心思想: 无须将所有的逻辑,粘合在一起实现。通过装饰者模式,可以将它们分解为3个几乎完全独立的组件,并在使用时灵活地进行装配。
/**
* 装饰接口 用于处理具体的内容
*
* @author PC
* @date 2022/07/12
**/
public interface IPacketCreator {
public String handleContent();
}
/**
* 具体组件,它的功能是构造要发布信息的核心内容
* 但不负责将其构造成一个格式工整的可直接发布的数据格式
* @author PC
* @date 2022/07/12
**/
public class PacketBodyCreator implements IPacketCreator{
@Override
public String handleContent() {
//构造核心数据,但不包括格式
return "Content of Packet";
}
}
/**
* 维护核心组件component对象,负责告知其子类
* 核心业务逻辑应该全权委托component完成,自己仅仅是做增强处理
* @author PC
* @date 2022/07/12
**/
public abstract class PacketDecorator implements IPacketCreator{
IPacketCreator component;
public PacketDecorator(IPacketCreator c){
component = c;
}
}
/**
* 拼接数据,其余业务处理依然交由内部component完成
*
* @author PC
* @date 2022/07/12
**/
public class PacketHTTPHeaderCreator extends PacketDecorator{
public PacketHTTPHeaderCreator(IPacketCreator c) {
super(c);
}
@Override
public String handleContent() {
StringBuffer sb = new StringBuffer();
sb.append("Cache-Control:no-cache\n");
sb.append(component.handleContent());
return sb.toString();
}
}
JDK实现中,例如OutputStream和InputStream类族的实现。OutputStream对象提供的方法比较简单,功能也比较弱,但通过各种装饰者的增强,OutputStream对象可以赋予强大的功能。FileOutputStream为系统核心类,实现了向文件写入数据。 使用DataOutputStream可以在FileOutputStream的基础上增加对多种数据类型的写操作支持,而BufferedOutputStream装饰器可以对FileOutputStream增加缓冲功能,从而优化I/O的性能。
** BufferedOutputStream为代表的性能组件是将性能模块和功能模块分离的一种典型实现