网站是怎么优化推广的,前程无忧招聘网站标记怎么做,wordpress数据库软件,东莞开发方案公司重修设计模式-创建型-工厂模式
一、概述
工厂模式#xff08;Factory Pattern#xff09;是设计模式中非常基础且常用的一种模式#xff0c;主要目的是通过封装对象的创建过程#xff0c;从而实现代码的解耦和灵活性的提升。
工厂模式的核心思想
封装对象的创建#x…重修设计模式-创建型-工厂模式
一、概述
工厂模式Factory Pattern是设计模式中非常基础且常用的一种模式主要目的是通过封装对象的创建过程从而实现代码的解耦和灵活性的提升。
工厂模式的核心思想
封装对象的创建将对象的创建过程封装起来使得客户端不必直接创建对象而是通过工厂类来间接创建对象。解耦将对象的创建与使用分离使得客户端只需要知道如何使用对象而不需要知道如何创建对象。提高扩展性当需要增加新的产品类时只需要增加一个具体的工厂类或产品类而不需要修改原有代码符合开闭原则对扩展开放对修改关闭。
工厂模式又细分为三种类型简单工厂、工厂方法和抽象工厂其中工厂方法和抽象工厂被收录在23种设计模式中而简单工厂被看做是工厂方法的一种特例。其实这三种工厂模式的原理和实现都非常简单重点在于搞清应用场景什么时候可以考虑使用工厂模式又该用这三种类型的哪一种呢
举个例子
应用需要根据传入的路径去解析文件并显示但文件可能有json、xml或yaml等格式需要根据后缀名来创建解析实现类。
需求很简单可以直接翻译成代码
fun loadConfig(path: String): Config? {var parser : IRuleConfigParser? nullif (path.endsWith(json, true)) {parser JsonRuleParser()} else if (path.endsWith(xml, true)) {parser XmlRuleParser()} else if (path.endsWith(yaml, true)) {parser YamlRuleParser()}val config parser?.parser(path)return config
}但“根据文件后缀名创建解析器”的逻辑是相对独立的可以将其抽成一个方法来复用但其实还可以将这部分逻辑抽成一个类让这个类来负责对象的创建从而更符合单一职责原则让代码更清晰而抽出的类就是简单工厂模式了。
二、简单工厂Simple Factory
又称静态工厂方法模式Static Factory Method Pattern简单工厂模式不是一种设计模式而更像是一种编程习惯。抽出的工厂类根据传入的参数决定创建出哪一种类的实例。
下面用简单工厂封装一下对象创建的代码
//简单工厂
class SimpleFactory {companion object {JvmStaticfun create(path: String): IRuleConfigParser? {return if (path.endsWith(json, true)) {JsonRuleParser()} else if (path.endsWith(xml, true)) {XmlRuleParser()} else if (path.endsWith(yaml, true)) {YamlRuleParser()} else null}}
}调用处
fun loadConfig(path: String): Config? {val parser SimpleFactory.create(path)val config parser?.parser(path)return config
}可以看到调用处代码非常简洁创建代码都被封装到工厂类中了开发中只要维护工厂代码即可。其实该例子创建的对象是可以复用的那么还可以在工厂类中通过 map 缓存创建的对象不必每次都创建新对象。同时 map 还可以取代 if-else 形式的代码
//带缓存的简单工厂
class SimpleFactory {companion object {JvmStaticprivate val cacheMap: HashMapString, IRuleConfigParser hashMapOf(json to JsonRuleParser(),xml to XmlRuleParser(),yaml to YamlRuleParser(),)JvmStaticfun create(path: String): IRuleConfigParser? {val extension getFileExtension(path)return cacheMap[extension]}JvmStaticfun getFileExtension(filePath: String): String {//...解析文件名获取扩展名比如rule.json返回jsonreturn filePath.substringAfterLast(., )}}
}简单工厂模式的问题是如果需要扩展新的产品类就需要修改工厂类的代码违反了开闭原则所以只适合改动不频繁的简单场景设计原则没必要严格遵守根据场景灵活使用才是目的
这里的解析器创建只是简单的 new 了一个对象如果解析器的创建流程变得复杂那 create() 方法中的代码也会随之变得冗长这种情况下可以把解析器复杂的创建逻辑进一步封装到各个工厂类中这就成了工厂方法模式。
三、工厂方法Factory Method
工厂方法模式定义一个用于创建对象的接口让子类决定实例化哪一个类。工厂方法让类的实例化延迟到子类中进行。这种方式的好处是新增产品类时只需要增加一个具体的产品类和对应的具体工厂类而不需要修改原有的工厂接口和工厂类。
下面使用工厂方法封装解析器创建流程
//封装每个解析器的创建过程
interface IRuleConfigParserFactory {fun create(): IRuleConfigParser
}//Json解析器创建
class JsonParserFactory : IRuleConfigParserFactory {override fun create(): IRuleConfigParser {val parser JsonRuleParser()//parser.xxx xxx//...return parser}
}//Xml解析器创建
class XmlParserFactory: IRuleConfigParserFactory {override fun create(): IRuleConfigParser XmlRuleParser()
}//Yaml解析器创建
class YamlParserFactory: IRuleConfigParserFactory {override fun create(): IRuleConfigParser YamlRuleParser()
}//这里其实还是简单工厂
class MethodFactory {companion object {JvmStaticfun create(path: String): IRuleConfigParser? {var parserFactory: IRuleConfigParserFactory? nullif (path.endsWith(json, true)) {parserFactory JsonParserFactory()} else if (path.endsWith(xml, true)) {parserFactory XmlParserFactory()} else if (path.endsWith(yaml, true)) {parserFactory YamlParserFactory()}return parserFactory?.create()}}
}外部调用
fun loadConfig(path: String): Config? {val parser MethodFactory.create(path)val config parser?.parser(path)return config
}可以看到复杂的解析器创建逻辑被隔离到具体的工厂创建类中了又用简单工厂简化了调用代码。可以发现简单工厂侧重对分支代码的封装而工厂方法更侧重隔离对象创建的复杂代码两者还可以组合使用。
工厂方法缺点是如果工厂不只是生产一种类型的对象或者说创建的对象会根据多个维度分类那工厂方法的实现类将会非常多从而难以维护。如上面的例子解析器除了根据文件格式分类还增加了文件大小的维度这时候需要实现的类就有 3 x 2 6个
SmallJsonParserFactory
SmallXmlParserFactory
SmallYamlParserFactory
BigJsonParserFactory
BigXmlParserFactory
BigYamParserFactory可见创建对象维度的增加会导致工厂类爆增针对上面场景就可以使用抽象工厂让一个工厂可以生产不同类型的对象。
四、抽象工厂Abstract Factory
抽象工厂模式使用抽象的接口来创建一系列相关或相互依赖的对象而无需指定它们具体的类。这种方式主要用于创建一组相互依赖或关联的对象而不需要指定它们具体的类。
以上面新增文件大小维度举例抽象出代码如下
//抽象工厂
interface IConfigParserFactory {fun createJsonFactory(): IRuleConfigParserfun createXmlFactory(): IRuleConfigParserfun createYamlFactory(): IRuleConfigParser
}//大文件解析器
class ConfigBigParser: IConfigParserFactory {override fun createJsonFactory(): IRuleConfigParser {//再这里创建不同维度的产品类return JsonRuleParser()}override fun createXmlFactory(): IRuleConfigParser {return XmlRuleParser()}override fun createYamlFactory(): IRuleConfigParser {return YamlRuleParser()}
}//小文件解析器
class ConfigSmallParser: IConfigParserFactory {override fun createJsonFactory(): IRuleConfigParser {//..省略return JsonRuleParser()}override fun createXmlFactory(): IRuleConfigParser {//..省略return XmlRuleParser()}override fun createYamlFactory(): IRuleConfigParser {//..省略return YamlRuleParser()}
}调用处代码
fun loadConfig3(path: String): Config? {//可根据具体业务通过抽象工厂创建不同的产品类无须关心实现类val parser1 ConfigBigParser()val parser2 ConfigSmallParser()parser1.createJsonFactory()parser1.createXmlFactory()parser1.createYamlFactory()parser2.createJsonFactory()parser2.createXmlFactory()parser2.createYamlFactory()
}抽象工厂模式是工厂方法模式的升级版本在有多个业务品种、业务分类时通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
总结
工厂模式是将对象创建的过程封装创建对象的复杂代码被隔离到每个工厂内部消化从而实现对象的创建与使用分离。不同工厂模式适用于不同的场景选择哪种模式取决于具体的需求和场景。