1. 程式人生 > >對裝飾器模式的理解

對裝飾器模式的理解

        我們為什麼使用裝飾器模式?

使用裝飾器模式能在不改變原始碼的基礎上,對原始碼的功能進行拓展,即為一個類新增一些功能,同時又不希望改變這個類原來的結構。我舉以下例子進行說明。

例如:我已經完成了一個日誌的介面和它的各個實現類,但是這些類只有輸出日誌到不同地方的功能,LoggerFileSystem能將日誌輸出到檔案系統(磁碟)中,LoggerCloud能將日誌輸出到雲端的某個檔案中。現在新需求來了,假如我想要在每條日誌輸出後順帶輸出這條日誌的時間,我們把它假設為功能一(functionOne);假如我還想再此基礎上輸出日誌內容,我們把它假設為功能二(functionTwo)。我們為日誌添加了功能而我們不想去修改每個實現類的方法,這時候就能使用裝飾者模式,為這個介面編寫一個裝飾類,修飾原來的日誌輸出。



log()定義日誌輸出的方法

/**
 * Created by AQ on 2018/7/11.
 */
public interface Logger {
    public void log();
}

LoggerCloud和LoggerFileSystem為原有的結構(我們未對日誌功能進行拓展時已存在)

/**
 * Created by AQ on 2018/7/11.
 */
public class LoggerCloud implements Logger {

    @Override
    public void log() {
        System.out.println("Log in Cloud");
    }
}
/**
 * Created by AQ on 2018/7/11.
 */
public class LoggerFileSystem implements Logger {
    @Override
    public void log() {
        System.out.println("Log in FileSystem");
    }
}

為Logger編寫一個裝飾器,拓展log()的功能,這個裝飾類要實現Logger介面並且擁有一個Logger成員

/**
 * Created by AQ on 2018/7/11.
 */
public class Decorator implements Logger {

    protected Logger logger;

    Decorator(Logger logger){
        this.logger=logger;
    }

    @Override
    public void log() {
        if(logger!=null){
            logger.log();
        }
    }
}

FunctionOne和FunctionTwo的newFunction()即我們想要新增的功能

/**
 * Created by AQ on 2018/7/11.
 */
public class FunctionTwo extends Decorator {

    FunctionTwo(Logger logger) {
        super(logger);
    }

    @Override
    public void log() {
        super.log();
        functionTwo();
    }

    public void functionTwo(){
        System.out.println("new function two");
    }
}

/**
 * Created by AQ on 2018/7/11.
 */
public class FunctionOne extends Decorator {

    FunctionOne(Logger logger) {
        super(logger);
    }


    public void newFunction(){
        System.out.println("new function one");
    }

    @Override
    public void log() {
        super.log();
        newFunction();
    }
}

main方法

public class Main {

    public static void main(String[] args) {
        Logger logger = new LoggerCloud();
        logger.log();
        System.out.println();
        Logger logger1 = new FunctionOne(logger);
        logger1.log();
        System.out.println();
        Logger logger2 = new FunctionTwo(logger1);
        logger2.log();
    }
}

輸出結果為

Log in Cloud

Log in Cloud
new function one

Log in Cloud
new function one
new function two

        結果分析

logger.log()呼叫的是LoggerCloud類中log()方法,輸出 Log in Cloud

logger1.log()呼叫的是FunctionOne類中的log()方法,先執行super.log(),即FunctionOne的父類Decorator的log()方法,由於在構造logger1時傳入的值是logger,所以此時Decorator的log()方法執行的是logger.log(),輸出Log in Cloud。然後執行到logger1.log()中的newFunction(),輸出new function one。

logger2.log()呼叫的是FunctionTwo類中的log()方法,先執行super.log(),即FunctionTwo的父類Decorator的log()方法,由於在構造logger2時傳入的值是logger1,所以此時Decorator的log()方法執行的是logger1.log(),

輸出 Log in Cloud

       new function one

然後執行到logger2.log()中的newFunction(),

        輸出new function two。

本文參考了https://blog.csdn.net/qq_24448899/article/details/78068813