设计模式-创建型-工厂模式
1. 简单工厂 Simple Factory
假设要做一个parser类,根据后缀来实例化Parser
public class RuleConfigSource {
public RuleConfig load(String ruleConfigFilePath) {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParser parser = RuleConfigParserFactory.createParser(ruleConfigFileExtension);
if (parser == null) {
throw new InvalidRuleConfigException(
"Rule config file format is not supported: " + ruleConfigFilePath);
}
String configText = "";
//从ruleConfigFilePath文件中读取配置文本到configText中
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private String getFileExtension(String filePath) {
//...解析文件名获取扩展名,比如rule.json,返回json
return "json";
}
}
public class RuleConfigParserFactory {
public static IRuleConfigParser createParser(String configFormat) {
IRuleConfigParser parser = null;
if ("json".equalsIgnoreCase(configFormat)) {
parser = new JsonRuleConfigParser();
} else if ("xml".equalsIgnoreCase(configFormat)) {
parser = new XmlRuleConfigParser();
} else if ("yaml".equalsIgnoreCase(configFormat)) {
parser = new YamlRuleConfigParser();
} else if ("properties".equalsIgnoreCase(configFormat)) {
parser = new PropertiesRuleConfigParser();
}
return parser;
}
}
上述代码是创建了工厂类,并且在工厂类当中制定了静态方法,根据输入参数的不同来分别实例化不同的parser。一般来说工厂当中创建对象的方法都是create开头,或者说明对于instance的操作,常见的方法名比如:
- createXXX()
- getInstance()
- createInstance()
- newInstance()
同样,如果要声明的类时很可能可以复用的,那么我们就可以在调用前就创建好,来节省对象创建的时间
public class RuleConfigParserFactory {
private static final Map<String, RuleConfigParser> cachedParsers = new HashMap<>();
static {
cachedParsers.put("json", new JsonRuleConfigParser());
cachedParsers.put("xml", new XmlRuleConfigParser());
cachedParsers.put("yaml", new YamlRuleConfigParser());
cachedParsers.put("properties", new PropertiesRuleConfigParser());
}
public static IRuleConfigParser createParser(String configFormat) {
if (configFormat == null || configFormat.isEmpty()) {
return null;//返回null还是IllegalArgumentException全凭你自己说了算
}
IRuleConfigParser parser = cachedParsers.get(configFormat.toLowerCase());
return parser;
}
}
2. 工厂方法
利用多态将if分支逻辑给去掉:
public interface IRuleConfigParserFactory {
IRuleConfigParser createParser();
}
public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory {
@Override
public IRuleConfigParser createParser() {
return new JsonRuleConfigParser();
}
}
public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory {
@Override
public IRuleConfigParser createParser() {
return new XmlRuleConfigParser();
}
}
public class YamlRuleConfigParserFactory implements IRuleConfigParserFactory {
@Override
public IRuleConfigParser createParser() {
return new YamlRuleConfigParser();
}
}
public class PropertiesRuleConfigParserFactory implements IRuleConfigParserFactory {
@Override
public IRuleConfigParser createParser() {
return new PropertiesRuleConfigParser();
}
}
// 关于如何选取需要import的factory,使用hashmap,相当于为工厂类创建了一个简单的工厂;一种委托给别人进行生产的模式思路
public class RuleConfigSource {
public RuleConfig load(String ruleConfigFilePath) {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParserFactory parserFactory = RuleConfigParserFactoryMap.getParserFactory(ruleConfigFileExtension);
if (parserFactory == null) {
throw new InvalidRuleConfigException("Rule config file format is not supported: " + ruleConfigFilePath);
}
IRuleConfigParser parser = parserFactory.createParser();
String configText = "";
//从ruleConfigFilePath文件中读取配置文本到configText中
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private String getFileExtension(String filePath) {
//...解析文件名获取扩展名,比如rule.json,返回json
return "json";
}
}
//因为工厂类只包含方法,不包含成员变量,完全可以复用,
//不需要每次都创建新的工厂类对象,所以,简单工厂模式的第二种实现思路更加合适。
public class RuleConfigParserFactoryMap { //工厂的工厂
private static final Map<String, IRuleConfigParserFactory> cachedFactories = new HashMap<>();
static {
cachedFactories.put("json", new JsonRuleConfigParserFactory());
cachedFactories.put("xml", new XmlRuleConfigParserFactory());
cachedFactories.put("yaml", new YamlRuleConfigParserFactory());
cachedFactories.put("properties", new PropertiesRuleConfigParserFactory());
}
public static IRuleConfigParserFactory getParserFactory(String type) {
if (type == null || type.isEmpty()) {
return null;
}
IRuleConfigParserFactory parserFactory = cachedFactories.get(type.toLowerCase());
return parserFactory;
}
}
2.1 工厂模式的好处
- 工程上一般来说使用工厂模式可以减少if else的使用,减少对于代码的侵入,可以通过反射来动态获取Bean
AbstractCart cart = (AbstractCart) applicationContext.getBean(userCategory + "UserCart"); return cart.process(userId, items);}
3. Dependency Injection 框架
依赖注入框架想要解决的是在基于Inversion of control的理念下,我们应该如何做,如何简化整个创建对象的过程。
DI容器底层最基本的设计思路是基于工厂模式来进行的,DI容器就相当于一个大的工厂类,复杂在程序启动的时候,根据配置(需要创建哪些类对象,每个类对象的创建需要依赖哪些其他类的对象)事先创建好对象。当应用程序需要使用某个类对象的时候,直接从容器当中获取即可。
DI容器的核心功能主要有:
- 配置解析
- 对象创建
- 对象生命周期管理
3.1 配置解析
应用需要告知DI容器需要创建哪些对象,需要将由DI容器来创建的类对象和创建类对象的必要信息,放到配置文件当中。容器读取配置文件,根据配置文件提供的信息来创建对象。像在spring当中,就是依靠xml文件或者注解,来告诉spring 用何种方式来创建对象。
3.2 对象创建
Spring当中将所有类对象的创建都放到了一个工厂类当中实现
3.3 对象生命周期管理
通过配置scope属性,决定是每次都返回一个新创建的对象还是每次都返回一个事先创建好的对象 – 单例对象
配置是否懒加载;lazy-init
- 真正被使用的时候被创建
- 在应用启动的时候就事先创建好
配置对象的init-method, destroy-method
- DI容器在创建好对象之后,会主动调用init-method属性指定的方法来初始化对象
- 在对象被最终销毁之前,DI容器会主动调用destroy-method属性指定的方法来做一些清理工作
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com
文章标题:设计模式-创建型-工厂模式
文章字数:1.3k
本文作者:Leilei Chen
发布时间:2020-06-15, 04:58:25
最后更新:2020-10-04, 00:24:52
原始链接:https://www.llchen60.com/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E5%88%9B%E5%BB%BA%E5%9E%8B-%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。