欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式:Logback中的工厂方法

程序员文章站 2024-01-10 09:42:40
...
简介

如果创建某个对象需要大量重复代码,应用层不关注这个对象的创建细节,创建对象的过程可以推迟到子类实现,那么可以考虑使用工厂方法。工厂模式是通过简单工厂演化而来,与简单工厂相比,在加入新产品时符合开闭原则,扩展性更高。然而每增加一种产品,都需要创建对应的工厂类,会导致类数量过多,增加系统的复杂度。但这种基于产品和工厂的多态性设计,正是工厂方法的关键。

举例

继续我们在简单工厂中教学视频的例子。其实只需要将原来的工厂类拆分成两层,抽象工厂和具体产品工厂。
抽象工厂中只需要定义创建产品的抽象方法,它可以是一个接口,也可以是抽象类。

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);
        }
    }
}
相关标签: 工厂方法