创建型模式-工厂方法


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

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设计模式-刘伟
posted @ 2018-09-17 17:36  David丁  阅读(91)  评论(0编辑  收藏  举报