(8)设计模式之装饰模式(结构型模式)

声明:以下都是博主浅薄的经验之谈,欢迎大家学习交流

使用场景

  • 我们在做系统设计的时候,一个非常重要的工作就是把大系统进行逐一的分解在分解。譬如用户管理模块、支付模块,但是每一个模块的某些业务功能都是通用。如在执行业务方法之前需进行这个操作:记录业务方法的操作日志;统计业务方法的执行时间;业务方法开始前开启事务,方法结束之后提交事务,方法异常回滚事务。
  • 于是就会产生如下类似的伪代码
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();
  • 是不是很灵活,我们要什么就包装什么。而且还可能指定包装的顺序从而实现代码执行的顺序。

声明:以上都是博主浅薄的经验之谈,欢迎大家学习交流

猜你喜欢

转载自blog.csdn.net/JavaMrZhang/article/details/74136284
今日推荐