一、原始类
有太多的if-else,语句。
package com.geek.jeep.designpattern.factory;
/**
* @author geek
* 演示工厂模式最原始的代码:
* 根据不同的配置文件,选择不同的文件解析器
* 封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
* 代码复用:创建代码抽离到独立的工厂类之后可以复用。
* 隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
* 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。
*/
public class RuleConfigSource {
public RuleConfig load(String ruleConfigFilePath) throws Exception {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParser parser = null;
if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new JsonRuleConfigParser();
} else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new XmlRuleConfigParser();
} else if ("yam".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new YamlRuleConfigParser();
} else {
throw new Exception("Rule config file format is not supported:"+ ruleConfigFilePath);
}
String configText = "";
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private String getFileExtension(String filePath) {
// 解析文件扩展名,如 rule.json 返回 json
return "json";
}
}
二、第一次改造
将if-else 剥离到函数中,抽象成方法
package com.geek.jeep.designpattern.factory;
/**
* @author geek
* <p>
* 剥离函数
*/
public class RuleConfigSource1 {
public RuleConfig load(String ruleConfigFilePath) throws Exception {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParser parser = createIRuleConfigParser(ruleConfigFileExtension);
String configText = "";
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private IRuleConfigParser createIRuleConfigParser(String ruleConfigFileExtension) throws Exception {
IRuleConfigParser parser = null;
if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new JsonRuleConfigParser();
} else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new XmlRuleConfigParser();
} else if ("yam".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new YamlRuleConfigParser();
} else {
throw new Exception("Rule config file format is not supported:" + ruleConfigFileExtension);
}
return parser;
}
private String getFileExtension(String filePath) {
// 解析文件扩展名,如 rule.json 返回 json
return "json";
}
}
三、第二次改造
为了让类的职责更加单一,代码更加清晰,
进一步 将 抽象方法,转移到了类里面, 新建一个工厂类 RuleConfigParserFactory
第一种工厂类:
package com.geek.jeep.designpattern.factory;
/**
* @author geek
*/
public class RuleConfigParserFactory {
public static IRuleConfigParser createIRuleConfigParser(String ruleConfigFileExtension) throws Exception {
IRuleConfigParser parser = null;
if ("json".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new JsonRuleConfigParser();
} else if ("xml".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new XmlRuleConfigParser();
} else if ("yam".equalsIgnoreCase(ruleConfigFileExtension)) {
parser = new YamlRuleConfigParser();
} else {
throw new Exception("Rule config file format is not supported:"+ ruleConfigFileExtension);
}
return parser;
}
}
package com.geek.jeep.designpattern.factory;
/**
* 为了让类的职责更加单一,代码更加清晰,
* 进一步 将 抽象方法,转移到了类里面, 新建一个工厂类 RuleConfigParserFactory
*/
public class RuleConfigSource2 {
public RuleConfig load(String ruleConfigFilePath) throws Exception {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
//第一种
IRuleConfigParser parser = RuleConfigParserFactory.createIRuleConfigParser(ruleConfigFileExtension);
//第二种
IRuleConfigParser parser2 = RuleConfigParserFactory2.createIRuleConfigParser(ruleConfigFileExtension);
String configText = "";
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private String getFileExtension(String filePath) {
// 解析文件扩展名,如 rule.json 返回 json
return "json";
}
}
第二种工厂类:
避免多次创建,实现复用。
package com.geek.jeep.designpattern.factory;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 简单工厂的第二种实现方式
*/
public class RuleConfigParserFactory2 {
private static final Map<String, IRuleConfigParser> cachedParsers = new HashMap<>();
static {
cachedParsers.put("json", new JsonRuleConfigParser());
cachedParsers.put("xml", new XmlRuleConfigParser());
cachedParsers.put("yam", new YamlRuleConfigParser());
}
public static IRuleConfigParser createIRuleConfigParser(String ruleConfigFileExtension) throws Exception {
if (StringUtils.isEmpty(ruleConfigFileExtension)) {
return null;
}
return cachedParsers.get(ruleConfigFileExtension.toLowerCase());
}
}
工厂方法
一、工厂类
package com.geek.jeep.designpattern.factory.method;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @author geek
* 工厂的工厂
*/
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("yam", new YamlRuleConfigParserFactory());
}
public static IRuleConfigParserFactory getParserFactory(String type) {
if (StringUtils.isEmpty(type)) {
return null;
}
return cachedFactories.get(type);
}
}
package com.geek.jeep.designpattern.factory.method;
import com.geek.jeep.designpattern.factory.IRuleConfigParser;
import com.geek.jeep.designpattern.factory.RuleConfig;
import com.geek.jeep.designpattern.factory.RuleConfigParserFactory;
import com.geek.jeep.designpattern.factory.RuleConfigParserFactory2;
/**
*
* @author geek
*/
public class RuleConfigSourceMap {
public RuleConfig load(String ruleConfigFilePath) throws Exception {
String ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParserFactory factory = RuleConfigParserFactoryMap.getParserFactory(ruleConfigFileExtension);
IRuleConfigParser parser = factory.createParser();
String configText = "";
RuleConfig ruleConfig = parser.parse(configText);
return ruleConfig;
}
private String getFileExtension(String filePath) {
// 解析文件扩展名,如 rule.json 返回 json
return "json";
}
}
package com.geek.jeep.designpattern.factory.method;
import com.geek.jeep.designpattern.factory.IRuleConfigParser;
/**
* @author geek
*/
public interface IRuleConfigParserFactory {
IRuleConfigParser createParser();
}
#--------------------------
package com.geek.jeep.designpattern.factory.method;
import com.geek.jeep.designpattern.factory.IRuleConfigParser;
import com.geek.jeep.designpattern.factory.JsonRuleConfigParser;
/**
* @author geek
* 工厂方法模式 : 利用多态
*/
public class JsonRuleConfigParserFactory implements IRuleConfigParserFactory{
@Override
public IRuleConfigParser createParser() {
return new JsonRuleConfigParser();
}
}
#--------------------------
package com.geek.jeep.designpattern.factory.method;
import com.geek.jeep.designpattern.factory.IRuleConfigParser;
import com.geek.jeep.designpattern.factory.XmlRuleConfigParser;
/**
* @author geek
*/
public class XmlRuleConfigParserFactory implements IRuleConfigParserFactory{
@Override
public IRuleConfigParser createParser() {
return new XmlRuleConfigParser();
}
}