美文网首页
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