工厂模式是创建类模式,主要是为了将类的实例化和使用相分离。正常来讲当我们要使用一个类的时候就直接new一下然后调用其方法就可以了,例子如下:
public class Client {
public static void main(String args[]) {
Logger logger;
logger = new FileLogger(); //FileLogger实现logger接口
logger.writeLog();
}
}
以上代码看似没有问题,可是当我们要实例化logger的另一种实现DataBaseLogger时问题就来了,我们将不得不修改Client的源码,这是违反“开闭原则”的。那么如何解决这个问题呢。有两种方法。
一:引入配置文件,利用java的反射机制动态实例化。
1:配置xml文件config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>com.logger.FileLogger</className>
</config>
2:定义XMLUtil类读取配置文件并返回实例对象
public class XMLUtil {
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getBean() {
try {
//创建DOM文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
String path="E:\\JAVA\\项目\\design\\src\\config.xml";
doc = builder.parse(new File(path));
//获取包含类名的文本节点
NodeList nl = doc.getElementsByTagName("className");
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
System.out.println(cName);
//通过类名生成实例对象并将其返回
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
3:在主方法中调用getBean动态得到实例类型
public class Client {
public static void main(String args[]) {
Logger logger;
logger = (Logger)XMLUtil.getBean();
logger.writeLog();
}
}
这样通过修改配置文件就可以在不修改源码的情况下改变实例化类型了。但是在编程时我们都强调将对象的创建和使用分离,这样不仅使系统更符合“单一职责原则”,也避免了用来实例化一个类的数据和代码在多个类中到处都是。为了进一步解决以上问题,在第一种方法的基础上再引入工厂模式。
二:工厂方法模式(在以上代码基础上实现)
1:logger接口下有FileLogger和DataBaseLogger两个实现,于是对应的我们在LoggerFactory接口下实现FileLoggerFactory和DataBaseLoggerFactory以分别实例化FileLogger和DataBaseLogger。
public interface LoggerFactory {
public Logger createLogger();
}
public class FileLoggerFactory implements LoggerFactory {
public Logger createLogger() {
//创建文件日志记录器对象
Logger logger = new FileLogger();
//创建文件,代码省略
return logger;
}
}
2:通过配置文件以及java反射动态实例化LoggerFactory,再调用createLogger()实例化出需要的Logger
public class Client {
public static void main(String args[]) {
LoggerFactory factory;
Logger logger;
factory = (LoggerFactory)XMLUtil.getBean();
logger = factory.createLogger();
logger.writeLog();
}
}