美文网首页
Decorator Pattern - 装饰器模式 - java

Decorator Pattern - 装饰器模式 - java

作者: thesam | 来源:发表于2018-08-20 23:12 被阅读7次

    装饰器模式注重扩展已有的功能。

    对于 装饰器模式 的使用场景,以及优缺点等说明,请参考 菜鸟教程|装饰器模式 ,这边文章里面已经说明的非常详细和清楚了。

    假设我们存在一个已有功能:PaymentService及其对应的实现PaymentServiceImpl

    这个是已经存在的借口:

    PaymentService.java
    
    public interface PaymentService {
        GatewayResponse collectMoney(Payment payment);
    }
    

    这个是已经存在的实现类:

    PaymentServiceImpl.java
    
    public class PaymentServiceImpl implements PaymentService {
        GatewayService gatewayService;
    
        @Override
        public GatewayResponse collectMoney(Payment payment) {
            return gatewayService.sale(payment);
        }
    }
    

    这个是已经存在的调用类:

    Main.java
    
    public class Main {
    
        public static void main(String[] args) {
            PaymentService paymentService = new PaymentServiceImpl();
    
            Payment p = new Payment() {};
    
            paymentService.collectMoney(p);
        }
    }
    

    当我感觉生活如此美好,可以领工资的时候,突然发现payment这么重要的业务竟然没有任何的监控,这个怎么能忍!!!于是,按照常规,我打算这样修改代码:

    PaymentServiceImpl.java
    
    public class PaymentServiceImpl implements PaymentService {
        GatewayService gatewayService;
        LogService logService;
    
        @Override
        public GatewayResponse collectMoney(Payment payment) {
            long start = System.currentTimeMillis(); // new code
            logService.log("payment.count", String.valueOf(1)); // new code
            GatewayResponse gr = gatewayService.sale(payment);
            long end = System.currentTimeMillis(); // new code
            logService.log("payment.cost", String.valueOf((end - start))); // new code
            logService.log("payment.count", String.valueOf(-1)); // new code
            return gr;
        }
    }
    

    嗯~~~
    新增加了五行代码来监控每个payment的持续时间已经对payment的个数统计。不过这五行代码和payment的业务本身一毛钱关系都没有,加到这里面真的是奇丑无比。而且现在是增加两个统计指标,以后要增加更多的指标,还得回来修改这个类。我们时刻要牢记什么是开闭原则:对扩展是开放的,对于修改是关闭的。
    是时候展示装饰器模式真正的实力了。
    通过需求,我们抽象出来日志的两个统计指标:1. 持续时间(duration);2. 计数器(counter)。这两个统计指标未来还可能改变,但是PaymentService的实现是不变的(起码暂时是不变的)。这样我们可以抽象出来两个独立的装饰器:PSDurationDecoratorPSCounterDecorator

    PSDurationDecorator.java
    
    // only focus on duration
    public class PSDurationDecorator implements PaymentService {
    
        private LogService logService;
    
        private PaymentService paymentService;
    
        public PSDurationDecorator(PaymentService paymentService) {
            this.paymentService = paymentService;
        }
    
        @Override
        public GatewayResponse collectMoney(Payment payment) {
            long start = System.currentTimeMillis();
            GatewayResponse gr = paymentService.collectMoney(payment);
            long end = System.currentTimeMillis();
            logService.log("payment.cost", String.valueOf((end - start)));
            return gr;
        }
    }
    

    对于调用方,我们只需要修改一行代码就可以了。

    Main.java
    
    public class Main {
    
        public static void main(String[] args) {
            // only need to change one line on client side
            PaymentService paymentService = new PSDurationDecorator(new PaymentServiceImpl()); 
    
            Payment p = new Payment() {};
    
            paymentService.collectMoney(p);
        }
    }
    

    PSCounterDecorator 的实现:

    PSCounterDecorator.java
    
    public class PSCounterDecorator implements PaymentService {
    
        private LogService logService;
    
        private PaymentService paymentService;
    
        public PSCounterDecorator(PaymentService paymentService) {
            this.paymentService = paymentService;
        }
    
        @Override
        public GatewayResponse collectMoney(Payment payment) {
            logService.log("payment.count", String.valueOf(1));
            GatewayResponse gr = paymentService.collectMoney(payment);
            logService.log("payment.count", String.valueOf(-1));
            return gr;
        }
    }
    

    对于调用方,增加一个新的指标也只需要修改一行代码就可以了。

    Main.java
    
    public class Main {
    
        public static void main(String[] args) {
            // only need to change one line on client side
            PaymentService paymentService = new PSCounterDecorator(new PSDurationDecorator(new PaymentServiceImpl()));
    
            Payment p = new Payment() {};
    
            paymentService.collectMoney(p);
        }
    }
    

    相关文章

      网友评论

          本文标题:Decorator Pattern - 装饰器模式 - java

          本文链接:https://www.haomeiwen.com/subject/eneriftx.html