Decorator Pattern - 裝飾器模式 - java 實現(xiàn)

裝飾器模式注重擴展已有的功能。

對于 裝飾器模式 的使用場景,以及優(yōu)缺點等說明,請參考 菜鳥教程|裝飾器模式 ,這邊文章里面已經(jīng)說明的非常詳細和清楚了。

假設(shè)我們存在一個已有功能:PaymentService及其對應(yīng)的實現(xiàn)PaymentServiceImpl。

這個是已經(jīng)存在的借口:

PaymentService.java

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

這個是已經(jīng)存在的實現(xiàn)類:

PaymentServiceImpl.java

public class PaymentServiceImpl implements PaymentService {
    GatewayService gatewayService;

    @Override
    public GatewayResponse collectMoney(Payment payment) {
        return gatewayService.sale(payment);
    }
}

這個是已經(jīng)存在的調(diào)用類:

Main.java

public class Main {

    public static void main(String[] args) {
        PaymentService paymentService = new PaymentServiceImpl();

        Payment p = new Payment() {};

        paymentService.collectMoney(p);
    }
}

當我感覺生活如此美好,可以領(lǐng)工資的時候,突然發(fā)現(xiàn)payment這么重要的業(yè)務(wù)竟然沒有任何的監(jiān)控,這個怎么能忍?。。∮谑?,按照常規(guī),我打算這樣修改代碼:

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;
    }
}

嗯~~~
新增加了五行代碼來監(jiān)控每個payment的持續(xù)時間已經(jīng)對payment的個數(shù)統(tǒng)計。不過這五行代碼和payment的業(yè)務(wù)本身一毛錢關(guān)系都沒有,加到這里面真的是奇丑無比。而且現(xiàn)在是增加兩個統(tǒng)計指標,以后要增加更多的指標,還得回來修改這個類。我們時刻要牢記什么是開閉原則:對擴展是開放的,對于修改是關(guān)閉的。
是時候展示裝飾器模式真正的實力了。
通過需求,我們抽象出來日志的兩個統(tǒng)計指標:1. 持續(xù)時間(duration);2. 計數(shù)器(counter)。這兩個統(tǒng)計指標未來還可能改變,但是PaymentService的實現(xiàn)是不變的(起碼暫時是不變的)。這樣我們可以抽象出來兩個獨立的裝飾器: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;
    }
}

對于調(diào)用方,我們只需要修改一行代碼就可以了。

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 的實現(xiàn):

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;
    }
}

對于調(diào)用方,增加一個新的指標也只需要修改一行代碼就可以了。

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);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容