之前我们有了解简单工厂模式:对象的创建和使用分离。相关了解可参照http://t.csdn.cn/vvmi8http://t.csdn.cn/vvmi8
对于简单工厂模式,我们想要增加一种产品类型我们需要修改工厂这个类,不符合开闭原则
今天介绍工厂方法模式:
目录
工厂方法模式:
UML:
工厂方法模式包含角色:
- Product抽象产品
- ConcreteProduct 具体产品
- Factory 抽象工厂
- ConcreteFactory 具体工厂
简单工厂模式就是一个工厂生产多种产品:通过参数不同生产不同的产品,抽象工厂模式就是一个工厂生产一种产品。
工厂方法应用实例:
某系统运行日志记录器(Logger)可以通过多种途径保存系统的运行日志,例如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。在设计各类日志记录器时,开发人员发现需要对日志记录器进行一些初始化工作,初始化参数的设置过程较为复杂,而且某些参数的设置有严格的先后次序,否则可能会发生记录失败。 为了更好地封装记录器的初始化过程并保证多种记录器切换的灵活性,现使用工厂方法模式设计该系统。
增加抽象层增加系统可扩展性:
java代码
抽象工厂:
public interface LoggerFactory {
//工厂方法
Logger createLogger();
}
具体工厂:
public class FileLoggerFactory implements LoggerFactory{
@Override
public Logger createLogger() {
System.out.println("正在创建文件日志记录器");
return new FileLogger();
}
}
public class DataBaseLoggerFactory implements LoggerFactory{
@Override
public Logger createLogger() {
System.out.println("正在创建数据库日志记录器");
return new DataBaseLogger();
}
}
抽象产品:
public interface Logger {
void writeLog();
}
具体产品:
public class FileLogger implements Logger {
@Override
public void writeLog() {
System.out.println("正在使用文件日志记录器记录日志");
}
}
public class DataBaseLogger implements Logger{
@Override
public void writeLog() {
System.out.println("正在使用数据库日志记录器记录日志");
}
}
客户类:
public class Client {
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
//创建工厂类,并强制转换
factory = (LoggerFactory)XMLUtil.getBean();
//调用工厂方法,创建产品对象
logger = factory.createLogger();
//调用日志记录方法
logger.writeLog();
}
}
配置文件及工具类:
public class XMLUtil {
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getBean() {
try {
//创建DOM文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("src//designpatterns//factorymethod//config.xml"));
//获取包含类名的文本结点
NodeList nl = doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
//通过类名生成实例对象并将其返回
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
<!— config.xml -->
<?xml version="1.0"?>
<config>
<className>designpatterns.factorymethod.FileLoggerFactory</className>
</config>
工厂方法模式符合开闭原则:
我们如果想要增加一个新的产品,我们需要增加一个新的具体工厂,一个具体产品。我们针对抽象层进行编程,通过修改配置文件即可。
工厂方法模式优点:
- 工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节
- 能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部
- 在系统中加入新产品时,完全符合开闭原则
工厂方法模式缺点:
每次写到这总会想起我们老师和我们说的话:世界上没有完美的设计模式。
类的数量会成对增加
工厂方法隐藏:
目的:为了进一步简化客户端的使用
实现:在工厂类中直接调用产品类的业务方法,客户端无须调用工厂方法创建产品对象,直接使用工厂对象即可调用所创建的产品对象中的业务方法
//将接口改为抽象类
public abstract class LoggerFactory {
//在工厂类中直接调用日志记录器类的业务方法writeLog()
public void writeLog() {
Logger logger = this.createLogger();
logger.writeLog();
}
public abstract Logger createLogger();
}