基础使用
工厂模式是创建型模式,是一种常用的获取对象实例的方式。
1、根据名称获取实例
思路:根据传入的类别名称,来分别实例化不同的实例。
/**
* 1、根据名称获取实例
* @param name 实例的名称
* @return
*/
public Object getObject(String name){
if(name == null){
return null;
}
if(name.equalsIgnoreCase("Object1")){
//返回名称对应的实例,简化demo,这里不新建类了
return new Object();
}
if(name.equalsIgnoreCase("Object2")){
//返回名称对应的实例,简化demo,这里不新建类了
return new Object();
}
if(name.equalsIgnoreCase("Object3")){
//返回名称对应的实例,简化demo,这里不新建类了
return new Object();
}
return null;
}
2、通过反射获取实例
根据名称获取的方式十分笨拙,随着业务的增长,工厂类会越来越重,代码耦合度太高,下面使用类的反射机制来获取实例。
/**
* 2、通过反射的方式,加载类
* 通过名称实例化的方式,需要在项目组耦合大量的类,且获取实例的逻辑会越来越复杂
* 这里通过反射简化
* @param clazz
* @return
*/
public Object getObject(Class clazz){
Object object = null;
try {
object = Class.forName(clazz.getName()).newInstance();
} catch (Exception e){
e.printStackTrace();
}
return object;
}
sl4j源码分析(摘要)
工厂模式的经典使用场景就是日志记录,sl4j在获取日志实例的时候会使用如下代码:
private static final Logger logger = LoggerFactory.getLogger(Factory.class);
下面我们来看看LoggerFactory
是如何获取日志实例的。
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
首先通过getILoggerFactory()
方法获取工厂类的实例,第一次调用时会进行初始化,无特殊配置会返回缺省的工厂实例,然后通过该工厂实例来实例化Logger
对象:
@Override
public final Logger getLogger(final String name) {
if (name == null) {
throw new IllegalArgumentException("name argument cannot be null");
}
// 如果访问主节点直接返回
if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
return root;
}
int i = 0;
Logger logger = root;
// 有缓存时直接返回
Logger childLogger = (Logger) loggerCache.get(name);
if (childLogger != null) {
return childLogger;
}
// 创建时,按照层级一层一层的创建下去
String childName;
while (true) {
int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
//当h == -1时,说明已经拿到了类的全路径名称
if (h == -1) {
childName = name;
} else {
childName = name.substring(0, h);
}
// move i left of the last point
i = h + 1;
synchronized (logger) {
childLogger = logger.getChildByName(childName);
if (childLogger == null) {
childLogger = logger.createChildByName(childName);
loggerCache.put(childName, childLogger);
incSize();
}
}
logger = childLogger;
//将最后一个节点实例化后返回
if (h == -1) {
return childLogger;
}
}
}
代码的具体逻辑已经在注释中标注出来,工厂模式的根本目的是将对象的创建和业务场景进行解耦,如sl4j中的LoggerFactory
可以获取项目中任意类的日志实例。