工厂模式分为简单工厂、工厂方法和抽象工厂,主要用于将复杂对象的创建抽象到一个专门的工厂类中,从而将对象的使用和构建解耦。
我们以一个配置解析的例子来说明一下工厂模式。
比如在java项目中,我们会把一些不经常改变的配置信息(比如数据库连接等),写入配置文件,而配置文件有很多类型,比如json、xml、properties
首先,我们使用简单工厂创建解析配置文件的解析器类对象
先定义一个配置类,文件里的内容最终会解析成一个config类
public class Config { }
多个文件解析器的抽象父类
public abstract class FileParser { public abstract Config parse(File file); }
三个文件解析器
public class JsonParser extends FileParser { @Override public Config parse(File file) { //省略具体解析逻辑 return new Config(); } } public class PropertiesParser extends FileParser { @Override public Config parse(File file) { //省略具体解析逻辑 return new Config(); } } public class XmlParser extends FileParser { @Override public Config parse(File file) { //省略具体解析逻辑 return new Config(); } }
解析器工厂类
/** * 简单工厂模式 * 根据不同的配置文件格式创建不同的解析器解析配置文件 */ public class ConfigParserFactory { public static FileParser createParser(File file) { String fileName = file.getName(); FileParser fileParser; if (fileName.endsWith("json")) { fileParser = new JsonParser(); } else if (fileName.endsWith("xml")) { fileParser = new XmlParser(); } else { fileParser = new PropertiesParser(); } return fileParser; } public static void main(String[] args) { File file = new File("D:/tipi/file.json"); FileParser fileParser = ConfigParserFactory.createParser(file); Config config = fileParser.parse(file); } }
上面的简单工厂没有省略掉if/else,只是将它抽取到了一个专门的工厂类中,如果想彻底省略掉if/else,可以使用工厂方法模式
首先我们定义一个工厂类接口
/** * 工厂方法 * 完全省略了if/else只是增加了不少factory类 * 每增加一种Parser,只需要新增一个parser类和对应的factory类即可,更加符合开闭原则 */ public interface ParserFactory { FileParser createParser(); }
然后为每个解析器都分别创建一个工厂
public class JsonParserFactory implements ParserFactory { @Override public FileParser createParser() { return new JsonParser(); } } public class PropertiesParserFactory implements ParserFactory { @Override public FileParser createParser() { return new PropertiesParser(); } } public class XmlParserFactory implements ParserFactory { @Override public FileParser createParser() { return new XmlParser(); } }
我们使用一个工厂的工厂来生成工厂
public class ConfigParserFactoryMap { private final static Map<String,ParserFactory> map=new ConcurrentHashMap<>(); static { map.put("json",new JsonParserFactory()); map.put("xml",new XmlParserFactory()); map.put("properties",new PropertiesParserFactory()); } public static ParserFactory get(String fileType){ return map.get(fileType); } public static void main(String[] args) { File file = new File("D:/config/file.xml"); String name = file.getName(); ParserFactory parserFactory = ConfigParserFactoryMap.get(name); FileParser parser = parserFactory.createParser(); Config config = parser.parse(file); } }