一. 简单工厂与实例工厂
1. 什么时候用简单工厂, 什么时候用实例工厂
- 当创建一个对象及其复杂, 只用 new 关键字不能表达的时候, 就可以用简单工厂模式, 将对象的创建过程写在一个静态方法里.
如下例子中, 根据文件名类型的不同, 按照不同方法解析文件, 形成配置类class RuleConfigSource { public RuleConfig load(String ruleConfigFilePath) throws Exception { String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath); // 简单工厂创建对象 IRuleConfigParser parser = RuleConfigFactory.createParser(ruleConfigFileExtension); String configText = ""; //从ruleConfigFilePath⽂件中读取配置⽂本到configText中 RuleConfig ruleConfig = parser.parse(configText); return ruleConfig; } private String getFileExtension(String filePath) { //...解析⽂件名获取扩展名,⽐如rule.json,返回json return "json"; } } // 简单工厂类 class RuleConfigFactory { /** * 简单⼯⼚模式的代码实现中,有多处 if 分⽀判断逻辑,违背开闭原则,但 * 权衡扩展性和可读性,这样的代码实现在⼤多数情况下(⽐如,不需要频繁地添加 * parser,也没有太多的 parser)是没有问题的。 */ public static IRuleConfigParser createParser(String ruleConfigFileExtension) throws Exception { IRuleConfigParser parser; if ("json".equalsIgnoreCase(ruleConfigFileExtension)) { parser = new JsonRuleConfigParser(); } else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) { parser = new XmlRuleConfigParser(); } else if ("yaml".equalsIgnoreCase(ruleConfigFileExtension)) { parser = new YamlRuleConfigParser(); } else if ("properties".equalsIgnoreCase(ruleConfigFileExtension)) { parser = new PropertiesRuleConfigParser(); } else { throw new Exception("Rule config file format is not supported: "); } return parser; } } interface IRuleConfigParser{} class JsonRuleConfigParser implements IRuleConfigParser{} class XmlRuleConfigParser implements IRuleConfigParser{} class YamlRuleConfigParser implements IRuleConfigParser{} class PropertiesRuleConfigParser implements IRuleConfigParser{}
- 如果在此基础上, 当创建的对象是一类对象中的某一类时 (比如上例中的 xmlParser, jsonParser, htmlParser就属于一类 parser 对象), 如果还要使用简工厂, 那么
判断创建出什么样的对象
这个判断逻辑, 就要全部使用 if-else 写在一个静态方法里. 当判断逻辑复杂时, 这些 if-else 就又变得丑陋, 于是将这个 if-else 判断规则抽成一个类, 用来判断返回哪个对象的创建方法, 这就需要用一个接口, 将对象的创建抽象出来, 再让不同的工厂类实现这个接口/** * 各种工厂对象的接口 */ interface IRuleConfigParserFactory { IRuleConfigParser createParser(); } class JsonRuleConfigParserFactory implements IRuleConfigParserFactory { public IRuleConfigParser createParser() { /** 这些工厂中创建对象的逻辑是不适用的, 如果创建对象只用new, 那根本不用使用工厂模式来创建对象, 工厂模式是为了封装复杂的创建对象逻辑*/ return new JsonRuleConfigParser(); } } class XmlRuleConfigParserFactory implements IRuleConfigParserFactory { public IRuleConfigParser createParser() { return new XmlRuleConfigParser(); } } class YamlRuleConfigParserFactory implements IRuleConfigParserFactory { public IRuleConfigParser createParser() { return new YamlRuleConfigParser(); } } class RuleConfigSource { /** 主要目标是完成从不同格式的文件中加载形成配置对象 */ public RuleConfig load(String ruleConfigFilePath) throws Exception { String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath); // RuleConfigParserFactoryMap.getParserFactory 判断使用哪个工厂的规则 IRuleConfigParserFactory parserFactory = RuleConfigParserFactoryMap.getParserFactory(ruleConfigFileExtension); if (parserFactory == null) { throw new Exception("Rule config file format is not supp"); } 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 ConcurrentHashMap<String, IRuleConfigParserFactory>(); static { cachedFactories.put("json", new JsonRuleConfigParserFactory()); cachedFactories.put("xml", new XmlRuleConfigParserFactory()); cachedFactories.put("yaml", new YamlRuleConfigParserFactory()); } public static IRuleConfigParserFactory getParserFactory(String type) { if (type == null || type.isEmpty()) { return null; } IRuleConfigParserFactory parserFactory = cachedFactories.get(type.toLowerCase(); return parserFactory; } }
二. 抽象工厂
抽象工厂和实例工厂的区别在于, 工厂接口的方法不止有一个,而是有多个. 这种区别主要用来表达, 使用第二个维度划分创建对象的种类. 即用工厂接口的不同方法名划分第二个维度. 实例工厂接口因为只有1个方法, 只能通过工厂的不同区分对象的种类, 只有一个维度上的区分
interface IConfigParserFactory {
IRuleConfigParser createRuleParser();
ISystemConfigParser createSystemParser();
//此处可以扩展新的parser类型,⽐如IBizConfigParser
}
class JsonConfigParserFactory implements IConfigParserFactory {
@Override
public IRuleConfigParser createRuleParser() {
return new JsonRuleConfigParser();
}
@Override
public ISystemConfigParser createSystemParser() {
return new JsonSystemConfigParser();
}
}
class XmlConfigParserFactory implements IConfigParserFactory {
@Override
public IRuleConfigParser createRuleParser() {
return new XmlRuleConfigParser();
}
@Override
public ISystemConfigParser createSystemParser() {
return new XmlSystemConfigParser();
}
// 省略YamlConfigParserFactory和PropertiesConfigParserFactory代码
}
interface ISystemConfigParser{}
class XmlSystemConfigParser implements ISystemConfigParser{}
class JsonSystemConfigParser implements ISystemConfigParser{}
网友评论