背景
设计模式是一个老生常谈的东西,但是写代码越久,对一些设计思想还是掌握的很模糊,也许在不经意间我们用到了某一种设计思想,但是有时候业务的迭代会让原有的设计愈发畸形,所以想针对每一种设计模式详细的分析分析,我打算用一个半月的时间讲透23种设计模式。(原谅我又立flag了😅)
我们就先从工厂模式说起 工厂模式分为 简单工厂,普通工厂,和抽象工厂,虽然都是工厂,但是其应用场景有着很大区别。
简单工厂
简单工厂我从内部就可以决议出我要的产品是什么,其内部堆叠了很多if else的逻辑,亦或者 通过swich case 来返回你需要的对象,比如这样:
static func createTool(with ToolType) -> Tool {
switch ToolType {
case ...:
return Camera()
case ...:
return Phone()
default:
}
}
上述代码中我们根据一个ToolType来生成我们所需要的对象,当然Camera和Phone要有一个公共的基类,这样通过多态的形式来得以实现简单工厂。
普通工厂
这里其实称之为工厂模式更为妥帖,为了有别于简单工厂,所以先以普通工厂称谓,当然我们经常把普通工厂和简单工厂混为一谈,接下来我们先假设一个场景,一个餐饮公司,我要生产奶茶和蛋糕,我当然可以用简单工厂的方式处理,但是随着我们品类的增加,我们多了牛排,咖啡。。。。我们create 的方法里面就要聚合大量的逻辑,且在对象实例化的时候,上游入口唯一,我们自定义的空间就会特别受限,如果说我们将上述的流程改成下面的结构,整个流程就变得清晰很多
我们有一个FoodFactory,CoffeeFactory 和BeefFactory继承于FoodFactory,然后两者可以重写父类的Creator的方法,来生产各自相应的产品,这里是咖啡和牛排,我们的代码就会变成这样
class Pruduct {}
class Beef: Pruduct {}
class Coffee: Pruduct {}
class FoodFactory {
func create() -> Pruduct {}
}
class BeefFactory: FoodFactory {
func create() -> Pruduct {
return
}
}
class CoffeeFactory: FoodFactory {
func create() -> Pruduct {
return
}
}
这样一来我们的代码完全解耦开来,各自有各自负责的内容,扩展的空间也很大
抽象工厂
接下来就是抽象工厂,我们还是接着上面的例子去延伸,我们现在的客户有的需要中式牛肉,通俗点儿说就是炒牛肉,而西式的做法就是牛排,有的客户需要中式咖啡,有的客户需要美式咖啡,这样以来,每种食物,又有了不同的风格,很多人看到这儿肯定会说这还不简单,接着在去扩展 create 方法不就好了,亦或者在积累加一个 createChines...依此类推, 但如果说,这时候又出现了泰式,法式,我们该怎么办呢,难道我们又要写一大堆if else吗 ,显然违背我们设计的初衷,不过抽象工厂很好的解决了这个问题,我们先给出代码
protocol AmericanPruduct {}
protocol ChinesePruduct {}
class ChinesBeef: ChinesePruduct {}
class ChinesCoffee: ChinesePruduct {}
class AmericanBeef: AmericanPruduct {}
class AmericanCoffee: AmericanPruduct {}
class FoodFactory {
func createChinese() -> ChinesePruduct {}
func createAmerican() -> AmericanPruduct {}
}
class BeefFactory: FoodFactory {
override func createChinese() -> ChinesBeef {}
override func createAmerica() -> AmericanBeef {}
}
class CoffeeFactory: FoodFactory {
override func createChinese() -> ChinesCoffee {}
override func createAmerica() -> AmericanCoffee {}
}
从代码上我们很容易看出我们对于产品进行了更深一步的抽象,而在基类中增加了两个create方法,以此来满足我们不同的需要。
当然该设计模式也有着优缺点
- 你可以确保同一工厂生成的产品相互匹配。
- 你可以避免客户端和具体产品代码的耦合。
- 单一职责: 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 开闭原则: 向应用程序中引入新产品变体时, 你无需修改客户端代码
缺点: 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂
总结
其实demo和类图是很好理解的,主要是应用,后续打算结合业务再补充一些具体的实现。