設計模式:Logback中的工廠方法

簡介

如果創建某個對象需要大量重複代碼,應用層不關注這個對象的創建細節,創建對象的過程可以推遲到子類實現,那麼可以考慮使用工廠方法。工廠模式是通過簡單工廠演化而來,與簡單工廠相比,在加入新產品時符合開閉原則,擴展性更高。然而每增加一種產品,都需要創建對應的工廠類,會導致類數量過多,增加系統的複雜度。但這種基於產品和工廠的多態性設計,正是工廠方法的關鍵。

舉例

繼續我們在簡單工廠中教學視頻的例子。其實只需要將原來的工廠類拆分成兩層,抽象工廠和具體產品工廠。
抽象工廠中只需要定義創建產品的抽象方法,它可以是一個接口,也可以是抽象類。

public abstract class VideoFactory {
    public abstract Video getInstance();
}

產品的創建就交由具體的工廠類實現,每種產品都有自己的工廠。

public class JavaVideoFactory extends VideoFactory {
    public Video getInstance() {
        return new JavaVideo();
    }
}
public class PythonVideoFactory extends VideoFactory {
    public Video getInstance() {
        return new PythonVideo();
    }
}

這裏的產品類和簡單工廠中一致,一個基類,一些實現基類的具體產品類。

public abstract class Video {
    private String name;
    private String describe;

    public abstract void produce();
}
public class JavaVideo extends Video {
    public void produce() {
        System.out.println("This is Java class.");
    }
}
public class PythonVideo extends Video {
    public void produce() {
        System.out.println("This is python class.");
    }
}

應用層只需要創建對應的工廠對象,調用統一的獲取產品對象方法即可。

public class Test {
    public static void main(String[] args) {
        VideoFactory videoFactory = new JavaVideoFactory();
        Video video = videoFactory.getInstance();
        video.produce();
    }
}

上文提過,工廠方法真正的實現了開閉原則。那我們就來需求擴展一下。加入現在又新增了一門MATLAB課程。(哈哈,原諒我對MATLAB的私心❤️
那麼我們只需要創建新的MATLAB工廠類和MATLAB視頻類分別繼承其基類即可,完全無需修改已有類。

public class MatlabVideoFactory extends VideoFactory {
    public Video getInstance() {
        return new MatlabVideo();
    }
}
public class MatlabVideo extends Video {
    public void produce() {
        System.out.println("This is MATLAB class.");
    }
}

當應用層需要時,只需創建MatlabVideoFactory對象,並從其中獲取即可。

public class Test {
    public static void main(String[] args) {
        VideoFactory videoFactory = new MatlabVideoFactory();
        Video video = videoFactory.getInstance();
        video.produce();
    }
}
Logback中的工廠方法

Logback在創建Log時,使用的就是工廠方法。它的各個元素都是在同一個類sun.rmi.runtime的Log.java中用內部類實現,但這並不影響工廠方法的結構。它的抽象產品基類就是Log,其中一個產品實現類爲LoggerLog,抽象工廠類爲LogFactory,工廠實現類爲LoggerLogFactory。另一對是LogStreamLog和LogStreamLogFactory。其中關鍵代碼如下,爲了更加易懂,我調整了一下源碼順序。

public abstract class Log {
  
    ... ...
    public abstract void log(Level var1, String var2);
    
    private interface LogFactory {
        Log createLog(String var1, String var2, Level var3);
    }
    
    private static class LoggerLog extends Log {
        public void log(Level var1, String var2) {
            if (this.isLoggable(var1)) {
                String[] var3 = Log.getSource();
                this.logger.logp(var1, var3[0], var3[1], Thread.currentThread().getName() + ": " + var2);
            }
        }
    }

    private static class LoggerLogFactory implements Log.LogFactory {
        public Log createLog(String var1, String var2, Level var3) {
            Logger var4 = Logger.getLogger(var1);
            return new Log.LoggerLog(var4, var3);
        }
    }
    
    private static class LogStreamLog extends Log {
        public void log(Level var1, String var2) {
            if (this.isLoggable(var1)) {
                String[] var3 = Log.getSource();
                this.stream.println(unqualifiedName(var3[0]) + "." + var3[1] + ": " + var2);
            }
        }
    }

    private static class LogStreamLogFactory implements Log.LogFactory {
        public Log createLog(String var1, String var2, Level var3) {
            LogStream var4 = null;
            if (var2 != null) {
                var4 = LogStream.log(var2);
            }
            return new Log.LogStreamLog(var4, var3);
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章