创建型模式之工厂方法模式

2018-11-12  本文已影响6人  sunpy

介绍

工厂方法模式本身是一种创建型模式,用来创建对象;工厂方法模式本身就是为每一个种类的对象创建一个对应的工厂来创建对象。


工厂方法模式UML图.png

实例代码

  1. 抽象产品类
public interface Product {
    public void produce();
}
  1. 具体产品类
/**
 * @description 具体产品:铁制产品
 * 
 * @author sunpy
 * @date 2018年11月12日  上午10:34:54
 */
public class SteelProduct implements Product{

    @Override
    public void produce() {
        System.out.println("生产铁制产品");
    }
}

/**
 * @description 具体产品:石制产品
 * 
 * @author sunpy
 * @date 2018年11月12日  上午10:35:11
 */
public class StoneProduct implements Product{

    @Override
    public void produce() {
        System.out.println("生产石制产品");
    }
}
  1. 抽象工厂类
/**
 * @description 抽象工厂
 * 
 * @author sunpy
 * @date 2018年11月12日  上午10:35:59
 */
public interface ProductFactory {

    public Product provide();
}
  1. 具体工厂类
public class StoneFactory implements ProductFactory {

    @Override
    public Product provide() {
        
        return new StoneProduct();
    }
}

public class SteelFactory implements ProductFactory{

    @Override
    public Product provide() {
        
        return new SteelProduct();
    }
}

实际应用的设计

工厂方法模式在slf4j中的日志工厂创建Logger类的应用

  1. 抽象工厂
public interface ILoggerFactory {

    public Logger getLogger(String name);
}
  1. 具体工厂
// log4j获取Logger的具体工厂类
public class Log4jLoggerFactory implements ILoggerFactory {
    ....

    public Logger getLogger(String name) {
        Logger slf4jLogger = loggerMap.get(name);
        if (slf4jLogger != null) {
            return slf4jLogger;
        } else {
            org.apache.log4j.Logger log4jLogger;
            if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME))
                log4jLogger = LogManager.getRootLogger();
            else
                log4jLogger = LogManager.getLogger(name);

            Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
            Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
            return oldInstance == null ? newInstance : oldInstance;
        }
    }
}

// slf4j默认的SubstituteLoggerFactory具体工厂类获取Logger
public class SubstituteLoggerFactory implements ILoggerFactory {
    ....
    
    synchronized public  Logger getLogger(String name) {
        SubstituteLogger logger = loggers.get(name);
        if (logger == null) {
            logger = new SubstituteLogger(name, eventQueue, postInitialization);
            loggers.put(name, logger);
        }
        return logger;
    }
}
  1. 抽象产品类
public interface Logger {
    ...
}
  1. 具体产品类
    Log4j只是额外加上了一个抽象模板类MarkerIgnoringBase ,让功能延伸到子类去实现的而已。我们还可以发现其又应用了类适配器模式,去适配LocationAwareLogger这个接口,这个不属于本篇内容,有空完整解析下slf4j的架构和设计模式。
// SubstituteLoggerFactory工厂生产的具体产品SubstituteLogger
public class SubstituteLogger implements Logger {
    ...
}


public abstract class MarkerIgnoringBase extends NamedLoggerBase implements Logger {

}

public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements LocationAwareLogger, Serializable {

}

总结

工厂方法模式vs简单工厂模式
简单工厂模式:将工厂类生产产品的逻辑进行了封装,虽然表面上抽象产品和具体产品实现了低耦合,但是工厂类和产品类却耦合在了一起,如果想增加一个新的产品却要修改工厂类,违背了开闭原则。
工厂方法模式:主要就是将工厂类和产品类进行了解耦,让一个工厂对应一类产品类,让不同种类的产品对应不同的工厂,增强了扩展性。

上一篇 下一篇

猜你喜欢

热点阅读