类创建型模式-工厂方法

简单工厂模式最大的缺点是当有新产品要加入到系统中时,必须修改工厂类,需要在其中加入必要的业务逻辑,这违背了“开闭原则”。此外,在简单工厂模式中,所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。

1. 定义

工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。

2. 结构

工厂方法模式提供一个抽象工厂接口来声明抽象工厂方法,而由其子类来具体实现工厂方法,创建具体的产品对象。工厂方法模式结构如图所示:

工厂方法

  • Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。
  • ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
  • Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
  • ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

3. 代码实现

产品接口

public interface Logger {
    void writeLog();
}

产品实现类1

public class FileLogger implements Logger {

    @Override
    public void writeLog() {
        System.out.println("写文件Log");
    }
}

产品实现类2

public class DatabaseLogger implements Logger {

    @Override
    public void writeLog() {
        System.out.println("写数据库log");
    }
}

工厂接口

public interface LoggerFactory {
    Logger createLogger();

    //重载的工厂方法
    Logger createLogger(String args);

    //使用该函数可隐藏工厂方法
    void writeLog();
}

工厂实现类1

public class FileLoggerFactory implements LoggerFactory {

    @Override
    public Logger createLogger() {
        Logger logger = new FileLogger();
        //进行相应的初始化操作
        return logger;
    }

    @Override
    public Logger createLogger(String args) {
        return null;
    }
    @Override
    public void writeLog() {
        Logger logger = new FileLogger();
        logger.writeLog();
    }
}

工厂实现类2

public class DatabaseLoggerFactory implements LoggerFactory {

    @Override
    public Logger createLogger() {
        Logger logger = new DatabaseLogger();
        //进行相应的初始化操作
        return logger;
    }

    @Override
    public Logger createLogger(String args) {
        return null;
    }

    @Override
    public void writeLog() {
        Logger logger = new DatabaseLogger();
        logger.writeLog();
    }
}

测试类

public class Test {

    public static void main(String[] args) {
        //这边可以利用反射从配置文件读取类名来获得具体的类
        //Class c=Class.forName(cName);
        //Object obj=c.newInstance();

        //调用工厂方法
        LoggerFactory loggerFactory = new FileLoggerFactory();
        Logger logger = loggerFactory.createLogger();
        logger.writeLog();

        //可在工厂接口中提供产品具体的函数来隐藏工厂方法的调用
        LoggerFactory loggerFactory2 = new DatabaseLoggerFactory();
        loggerFactory2.writeLog();
    }
}
//写文件Log
//写数据库log

4. 优缺点

  • 优点
  1. 用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  2. 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。
  3. 在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,符合“开闭原则”。
  • 缺点
  1. 加新产品需编写新的具体类和对应的工厂类,增加系统复杂性和额外开销。
  2. 在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。

5. 适用场景

  1. 客户端不知道它所需要的对象的类,只需要知道对应的工厂类。
  2. 抽象工厂类通过其子类来指定创建哪个对象,利用对象多态和里氏变换原则,使得系统更易扩展。

6. 个人理解

  1. 工厂方法符合“开闭原则”,通过工厂接口的子类来实现系统的可扩展,系统扩展的时候只需添加产品类及其对应的工厂实现类即可。

参考

  1. Java设计模式-刘伟

猜你喜欢

转载自www.cnblogs.com/ading-blog/p/9663438.html