模式定义
工厂方法模式(Factory Method Pattern):又名工厂模式,虚拟构造器(Virtual Constructor)模式、多态工厂模式(Polymorphic Factory)模式,它属于类创建型。在该模式中工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体产品对象。这样可通过共产子类来确定究竟应该实例化哪一个具体产品类。
模式结构
1、Product(抽象产品)
抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口。
2、ConcreteProduct(具体产品)
具体产品实现了抽象产品接口,某种类型的具体产品有专门的具体工厂创建,它们之间一一对应。
3、Factory(抽象工厂)
在其中声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口。
4、ConcreteFactory(具体工厂)
是抽象工厂的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例。
模式的优缺点
优点
增加新的产品类时无需修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性,符合“开闭原则”。
缺点
增加新的产品的同时需要增加新的工厂,导致系统类的规格书成对增加,在一定程度上增加了系统的复杂性。
模式的适用情况
一个类不知道它所需要的对象的类;另一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个.客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定。
题目
某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志,现使用工厂方法模式设计该系统。
思维构图
代码及运行结果
1、主要代码
1)抽象产品类Log(日志类)可以是一个接口,也可以是一个抽象类,其中包含了所有产品都具有的业务方法
public interface Log {
public void writeLog();
}
2)具体产品类FileLog(文件日志类),是一种具体产品,实现了在Log接口中定义的业务方法writeLog()
public class FileLog implements Log {
public void writeLog() {
System.out.println("文件记录...");
}
}
3)具体产品类DatabaseLog(数据库日志类)
public class DatabaseLog implements Log {
@Override
public void writeLog() {
System.out.println("数据库记录...");;
}
}
4)抽象工厂类LogFactory(日志工厂类),包含了抽象工厂方法createLog(),返回一个抽象产品Log类型的对象。
public interface LogFactory {
public Log productTV();
}
5)具体工厂类FileLogFactory(文件日志工厂类),实现抽象方法createLog(),在工厂方法中创建并返回一个对象的具体产品。
public class FileLogFactory implements LogFactory {
@Override
public Log productTV() {
System.out.println("创建日志选择文件记录");
return new FileLog();
}
}
6)具体工厂类DatabaseLogFactory
public class DatabaseLogFactory implements LogFactory {
@Override
public Log productTV() {
System.out.println("创建日志选择数据库记录");
return new DatabaseLog();
}
}
2、辅助代码
1)XML操作工具类XMLUtil
public class XMLUtil {
public static Object getBean(){
try {
DocumentBuilderFactory dFactory =DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc =builder.parse(new File("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;
}
}
}
2)配置文件config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>one.FileLogFactory</className>
</config>
3)客户端测试类Client
public class Client {
public static void main(String[] args) {
try {
Log log;
LogFactory fac;
fac = (LogFactory) XMLUtil.getBean();
log = fac.productTV();
log.writeLog();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}