细说设计模式:1.工厂模式

107 阅读4分钟

背景

设计模式是一个老生常谈的东西,但是写代码越久,对一些设计思想还是掌握的很模糊,也许在不经意间我们用到了某一种设计思想,但是有时候业务的迭代会让原有的设计愈发畸形,所以想针对每一种设计模式详细的分析分析,我打算用一个半月的时间讲透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 的方法里面就要聚合大量的逻辑,且在对象实例化的时候,上游入口唯一,我们自定义的空间就会特别受限,如果说我们将上述的流程改成下面的结构,整个流程就变得清晰很多

截屏2023-08-17 19.00.37.png

我们有一个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 
    }
}

这样一来我们的代码完全解耦开来,各自有各自负责的内容,扩展的空间也很大 截屏2023-08-17 18.24.03.png

抽象工厂

接下来就是抽象工厂,我们还是接着上面的例子去延伸,我们现在的客户有的需要中式牛肉,通俗点儿说就是炒牛肉,而西式的做法就是牛排,有的客户需要中式咖啡,有的客户需要美式咖啡,这样以来,每种食物,又有了不同的风格,很多人看到这儿肯定会说这还不简单,接着在去扩展 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方法,以此来满足我们不同的需要。

当然该设计模式也有着优缺点

  •  你可以确保同一工厂生成的产品相互匹配。
  • 你可以避免客户端和具体产品代码的耦合。
  • 单一职责: 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
  • 开闭原则: 向应用程序中引入新产品变体时, 你无需修改客户端代码

缺点: 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂

截屏2023-08-17 19.14.21.png

总结

其实demo和类图是很好理解的,主要是应用,后续打算结合业务再补充一些具体的实现。