声明:以下都是博主浅薄的经验之谈,欢迎大家学习交流
- 博主是参考这个视频进行学习总结的:
- 设计模式学习视频(点击我)
- 提取码 : 29oc
使用场景
- 我们在做系统设计的时候,一个非常重要的工作就是把大系统进行逐一的分解在分解。譬如用户管理模块、支付模块,但是每一个模块的某些业务功能都是通用。如在执行业务方法之前需进行这个操作:记录业务方法的操作日志;统计业务方法的执行时间;业务方法开始前开启事务,方法结束之后提交事务,方法异常回滚事务。
- 于是就会产生如下类似的伪代码
public void PayService{
public Response execute()
{
logger.debug("....");//记录日志
RecordTimeUtiles.startTime();//记录业务方法执行时间
//执行业务方法的的代码...
//......
//......
RecordTimeUtiles.endTime();
}
}
虽然这样的代码实现了功能,但是可想而知后续增加更多的业务功能方法,也都是需要重复以上的代码。
此时可以应用模板方法设计模式来解决以上大部分代码重复的问题。
- AbstractService.java
public abstract class AbstractService{
public void execute(){
logger.debug("....");//记录日志
RecordTimeUtiles.startTime();//记录业务方法执行时间
//执行业务方法的的代码...
//......
payServiceExecute();
//......
RecordTimeUtiles.endTime();
}
public abstract Response payServiceExecute();
}
- PayService.java
public class PayService extends AbstractService{
public Response payServiceExecute(){
//执行业务方法的的代码...
//......
//......
}
}
- 此时父类AbstractService.java 已经将原先的记录日志、方法执行时间等重复性的代码都写好了,而子类PayService.java只需要通过实现父类的抽象方法【payServiceExecute】去实现自己需要的业务功能代码即可!
调用的方式很简单如下:
AbstractService as = new PayService();
as.execute();
- 缺点:这样的方式最大的缺陷就是父类定义了一切,子类要毫无保留的去服从。什么执行顺序啥的,都不是子类所能控制的,假如某个子类不要统计方法的时间只要记录日志,此时这样的设计方法就无能为力了。
装饰模式
如果利用装饰模式,针对上面问题将会带来更大的灵活性,且看!
Service.java
public interface Service{
Response execute();
}
- LogDecorator.java
public class LogDecorator implements Service{
private Service service;
public LogDecorator (Service service){
this.service = service;
}
public Response execute(){
logger.debug("....");//记录日志
this.service.execute();
}
}
- RecordTimeDecorator.java
public class RecordTimeDecorator implements Service{
private Service service;
public RecordTimeDecorator(Service service){
this.service = service;
}
public Response execute(){
RecordTimeUtiles.startTime();//记录业务方法执行时间
this.service.execute();
RecordTimeUtiles.endTime();
}
}
- PayService.java
public class PayService implements Service{
public Response execute(){
//执行业务方法的的代码...
//......
}
}
- 调用方式
//场景一:只需要记录日志
Service service = new LogDecorator(new PayService());
service.execute();
//场景二:只需要记录业务方法执行的时间
Service service = new RecordTimeDecorator(new PayService());
service.execute();
//场景三:需要记录日志;记录业务方法执行的时间
Service service = new RecordTimeDecorator(new LogDecorator(new PayService()));
service.execute();
- 是不是很灵活,我们要什么就包装什么。而且还可能指定包装的顺序从而实现代码执行的顺序。
声明:以上都是博主浅薄的经验之谈,欢迎大家学习交流
- 博主是参考这个视频进行学习总结的,如阅读不懂可参看本视频哦!
- 设计模式学习视频(点击我)
- 提取码 : ivtk