一、什么是装饰器设计模式
装饰器模式(Decorator Pattern),是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 使用装饰器模式的时候需要注意一下几点内容:
- 装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。
- 装饰对象包含一个真实对象的引用。
- 装饰对象接受所有的来自客户端的请求,它把这些请求转发给真实的对象。
- 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。然而,装饰者模式,可以在应用程序运行时,动态扩展功能,更加方便、灵活。 适用装饰者模式场。
- 在我们想给一个类扩展多种功能时,可以使用装饰者设计模式进行多层装饰,这样我们可以把具体的扩展功能分开,如过再需要扩展功能时,只需要再增加装饰类即可,只需要在客户端调用时使用就好,减少了代码的耦合性,增加了可扩展性。
二、装饰器设计模式结构图
- Component定义的是一个接口,可以给这些对象动态的添加功能
- ConcreteComponent是一个具体的类,是 Component 接口的实现类,我们主要是为了给这些具体的实现类来扩展一些功能
- Decorator是装饰抽象类,继承 Component 接口,扩展 Component 的功能,但是对于 Component 来说,无需知道 Decorator 的存在
- ConcteteDecorator是具体的装饰类,起到给ConcreteComponent类扩展功能的的作用
上图是装饰器模式的完整结构,但实际运用当中有很多可以变化的地方,如:
- Component 可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)
- 装饰器的抽象父类 Decorator 并不是必须的,这时,装饰器模式和静态代理模式非常的相似,区别就在于装饰器模式在装饰类中将被装饰的类当参数传入,需要装饰哪个类由客户端调用来决定,而静态代理则是在代理类中就已经把被代理的类明确了。
三、装饰器模式写法举例
下面,我们装饰器设计模式来实现一个功能:从数据库查询出一段内容,然后替换两处指定内容
首先,是待装饰的抽象类,相当于 Component
public abstract class AbstractProcessor<T, R> { public abstract RetMsg<R> doProcessor(T t); }
然后是它的一个子类,相当于实现类 ConcreteComponent
public class MockProcessor extends AbstractProcessor<MockRequestDTO, String> { @Override public RetMsg<String> doProcessor(MockRequestDTO mockRequestDTO) { String mockData = getMockDataFromDB(mockRequestDTO).getData(); return RetMsg.buildSuccessMsg(mockData); } private RetMsg<String> getMockDataFromDB(MockRequestDTO mockRequestDTO){ // 从数据库中去查数据 Set<MappingConfDO> mappingConfs = DaoFacade.of().mapping(MappingConfMapper.class, mapper -> mapper.queryByUrlAndHost(mockRequestDTO.getMockUrl(), mockRequestDTO.getRemoutHost())); if (mappingConfs.isEmpty()) { return RetMsg.buildFailedMsg("没有找到匹配数据"); } if (mappingConfs.size() > 1) { return RetMsg.buildFailedMsg("找到的匹配数据太多"); } // 这是找到了我们所要的那个匹配,并将MappingConfDO转化为MappingConfDTO MappingConfDTO mappingConfDTO = mappingConfs.stream().map(MappingConfDO::toMappingConfDTO).findFirst().get(); // 从 response_data 表查出数据,返回的是ResponseDataDO对象 ResponseDataDO responseDataDO = DaoFacade.of().mapping(ResponseDataMapper.class, mapper -> mapper.quaryByMappingId(mappingConfDTO.getMappingId())); return RetMsg.buildSuccessMsg(responseDataDO.getData()); } }
以上 MockProcessor 类的 doProcessor() 方法是从数据库中查询匹配的数据。假设我们查出来的数据的格式:AAA &{date:yyyy-MM-dd HH:mm:ss} BBB &{id:16},我们需要对这段数据中的 date 和 id 后面的字符串根据一定规则进行替换。
接下来抽象装饰父类,相当于 Decorator
public class AbstractDecorator extends AbstractProcessor<MockRequestDTO,String> { protected AbstractProcessor<MockRequestDTO,String> processor; public AbstractDecorator(AbstractProcessor<MockRequestDTO, String> processor) { this.processor = processor; } @Override public RetMsg<String> doProcessor(MockRequestDTO mockRequestDTO) { return processor.doProcessor(mockRequestDTO); } }
AbstractDecorator
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:设计模式之 ==> 装饰器设计模式 - Python技术站