一、简单工厂模式存在的问题:
当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背“开闭原则”。
要实现增加新产品的同时还不修改工厂类,就产生了工厂模式。
二、工厂模式简介
在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。工厂方法模式定义如下:
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。
工厂方法模式提供一个抽象工厂接口来声明抽象工厂方法,而由其子类来具体实现工厂方法,创建具体的产品对象。工厂方法模式结构如图2所示:
与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂可以是接口,也可以是抽象类或者具体类,其典型代码如下所示:
interface Factory { public Product factoryMethod(); }
在抽象工厂中声明了工厂方法但并未实现工厂方法,具体产品对象的创建由其子类负责,客户端针对抽象工厂编程,可在运行时再指定具体工厂类,具体工厂类实现了工厂方法,不同的具体工厂可以创建不同的具体产品,其典型代码如下所示:
class ConcreteFactory implements Factory { public Product factoryMethod() { return new ConcreteProduct(); } }
在实际使用时,具体工厂类在实现工厂方法时除了创建具体产品对象之外,还可以负责产品对象的初始化工作以及一些资源和环境配置工作,例如连接数据库、创建文件等。
典型的客户端类代码片段如下所示:
…… Factory factory; factory = new ConcreteFactory(); //可通过配置文件实现 Product product; product = factory.factoryMethod(); ……
三、实例
Sunny公司开发人员决定使用工厂方法模式来设计日志记录器,其基本结构如图3所示:
图3 日志记录器结构图
在图3中,Logger接口充当抽象产品,其子类FileLogger和DatabaseLogger充当具体产品,LoggerFactory接口充当抽象工厂,其子类FileLoggerFactory和DatabaseLoggerFactory充当具体工厂。完整代码如下所示:
//日志记录器接口:抽象产品 interface Logger { public void writeLog(); }
//数据库日志记录器:具体产品
class DatabaseLogger implements Logger { public void writeLog() { System.out.println("数据库日志记录。"); } }
//文件日志记录器:具体产品
class FileLogger implements Logger { public void writeLog() { System.out.println("文件日志记录。"); } }
//日志记录器工厂接口:抽象工厂
interface LoggerFactory { public Logger createLogger(); }
//数据库日志记录器工厂类:具体工厂
class DatabaseLoggerFactory implements LoggerFactory { public Logger createLogger() { //连接数据库,代码省略 //创建数据库日志记录器对象 Logger logger = new DatabaseLogger(); //初始化数据库日志记录器,代码省略 return logger; } }
//文件日志记录器工厂类:具体工厂
class FileLoggerFactory implements LoggerFactory { public Logger createLogger() { //创建文件日志记录器对象 Logger logger = new FileLogger(); //创建文件,代码省略 return logger; } }
编写如下客户端测试代码:
class Client { public static void main(String args[]) { LoggerFactory factory; Logger logger; factory = new FileLoggerFactory(); //可引入配置文件实现 logger = factory.createLogger(); logger.writeLog(); } }
编译并运行程序,输出结果如下:
文件日志记录。