工厂方法模式
Factory Method Pattern:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化,工厂方法模式让一个类的实例化延迟到子类。
工厂方法模式简称为工厂模式,或者称作虚拟构造器模式
角色:抽象产品、具体产品、抽象工厂、具体工厂
代码
// 抽象产品
public interface Logger {
public 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 interface LoggerFactory {
public Logger createLogger(); // 抽象工厂方法
}
// 具体工厂
public class FileLoggerFactory implements LoggerFactory{
@Override
public Logger createLogger() {
return new FileLogger();
}
}
// 具体工厂
public class DatabaseLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
return new DatabaseLogger();
}
}
为了实现开闭原则,引入配置文件及其工具类
// config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<config> <className>com.nq.FMP.DatabaseLoggerFactory</className>
</config>
// 工具类
public class XMLUtil {
public static Object getBean() {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src\\com\\nq\\FMP\\config.xml"));
NodeList nodeList = document.getElementsByTagName("className");
Node node = nodeList.item(0).getFirstChild();
String cName = node.getNodeValue().trim();
Class<?> c = Class.forName(cName);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
// 客户端测试类
public class Client {
public static void main(String[] args) {
LoggerFactory factory;
Logger logger;
factory = (LoggerFactory) XMLUtil.getBean();
logger = factory.createLogger();
logger.writeLog();
}
}
优点
- 用户只需要关心所需产品对应的工厂,无需关心创建细节
- 基于工程角色和产品角色的多态性设计
- 在系统中加入新产品时无需修改抽象工厂和抽象产品提供的接口,无需修改客户端和其它具体的工厂和具体的产品
缺点
- 增加系统的复杂度和额外的开销
- 增加了系统的抽象性和理解难度
适用场景
- 客户端不知道所需要的类,只需要知道具体的工厂
- 抽象工厂通过其子类指定创建哪个对象