🐻设计模式之工厂三兄弟

2,441 阅读3分钟

熊二:工厂模式三兄弟,听说过没?

熊大:......

熊二:工厂模式三兄弟是:简单工厂模式、工厂方法模式、抽象工厂模式,这三种都是属于创建型的设计模式。

之前你不是问如何进行App架构设计吗?设计模式三兄弟就是很好的例子。

熊大:为什么这么说呢?

熊二:因为工厂模式三兄弟可以根据功能的复杂程度,进行升级和降级;根据功能改变,这扩展性不就体现出来了吗,同时也能减小代码解耦程度,一举多得。

创建型模式

工厂三兄弟 脑图结构

创建型模式中的 工厂三兄弟适用于创建的对象有极大类似性的场景。

简单工厂模式

简单工厂模式,违反了设计原则中的开闭原则。我们具体看代码。

protocol Product {}
class ConcreteProductA: Product {}
class ConcreteProductB: Product {}
class Client {
    let s = Factory()
}
class Factory {
    func createProduct(type: Int) -> Product {
        if type == 0 {
            return ConcreteProductA()
        } else {
            return ConcreteProductB()
        }
    }
}
let c = Client()
c.s.createProduct(type: 0) // get ConcreteProductA

分析:

每次新增一种type,都要修改if else ,即我们可能会频繁修改内部核心代码,这就违反了开闭原则。

针对关于此段代码,我们再来分析一下。

第一点:

此代码是通过protocol 来实现的,不是定义父类,使用继承关系;
个人认为protocol更适合横向的,继承更适合纵向的;
工厂模式使用继承应该更好一点;

第二点:

此外,type 不要出现 0、1、2、3之类的,
应该使用枚举,不然这些魔鬼数字不易读懂;
我们的代码要具有可读性,代码要让人看着爽。

第三点:

而且明显,type未来会有很多个,所以考虑扩展性,这里用if、else条件语句,
就不如swith 语句,在这里 switch 将是更优雅、更具有扩展性的一种方式。

为了方便接下来分析,代码展示我就不对代码进行修改,希望诸君知晓,如果有不同观点,欢迎入群solo。代码是这位兄弟的

工厂模式

工厂模式相对于简单工厂模式而言只是将创建工作分给了子类,依旧没有解决简单工厂模式关于违反开闭原则的问题。

protocol Product {}
class ConcreteProductA: Product {}
class ConcreteProductB: Product {}
class Client {
    let f = Factory()
}
class Factory {
    func createProduct() -> Product? { return nil } // 用于继承
    func createProduct(type: Int) -> Product? { // 用于调用
        if type == 0 {
            return ConcreteFactoryA().createProduct()
        } else {
            return ConcreteFactoryB().createProduct()
        }
    }
}
class ConcreteFactoryA: Factory {
    override func createProduct() -> Product? {
        // ... 产品加工过程
        return ConcreteProductA()
    }
}
class ConcreteFactoryB: Factory {
    override func createProduct() -> Product? {
        // ... 产品加工过程
        return ConcreteProductB()
    }
}
let c = Client()
c.f.createProduct(type: 0) // get ConcreteProductA

抽象工厂模式

简单工厂模式、工厂模式生产都是同一种类型的产品,有共同的父类。

当你的产品需要用两个及以上时就要升级成抽象工厂模式了。

protocol ProductA {}
class ConcreteProductA1: ProductA {}
class ConcreteProductA2: ProductA {}
protocol ProductB {}
class ConcreteProductB1: ProductB {}
class ConcreteProductB2: ProductB {}
class Client {
    let f = Factory()
}
class Factory {
    func createProductA() -> ProductA? { return nil } // 用于继承
    func createProductB() -> ProductB? { return nil } // 用于继承
    func createProductA(type: Int) -> ProductA? { // 用于调用
        if type == 0 {
            return ConcreteFactory1().createProductA()
        } else {
            return ConcreteFactory2().createProductA()
        }
    }
    func createProductB(type: Int) -> ProductB? { // 用于调用
        if type == 0 {
            return ConcreteFactory1().createProductB()
        } else {
            return ConcreteFactory2().createProductB()
        }
    }
}
class ConcreteFactory1: Factory {
    override func createProductA() -> ProductA? {
        // ... 产品加工过程
        return ConcreteProductA1()
    }
    override func createProductB() -> ProductB? {
        // ... 产品加工过程
        return ConcreteProductB1()
    }
}
class ConcreteFactory2: Factory {
    override func createProductA() -> ProductA? {
        // ... 产品加工过程
        return ConcreteProductA2()
    }
    override func createProductB() -> ProductB? {
        // ... 产品加工过程
        return ConcreteProductB2()
    }
}
let c = Client()
c.f.createProductA(type: 0) // get ConcreteProductA1
c.f.createProductA(type: 1) // get ConcreteProductA2
c.f.createProductB(type: 0) // get ConcreteProductB1
c.f.createProductB(type: 1) // get ConcreteProductB2

关于三兄弟的升级与降级

  • 单一类型产品比较少时,用简单工厂模式。
  • 单一类型产品各种定制比较多时,用工厂模式。
  • 多种类型产品时,使用抽象工厂模式。

参考

本文代码段参考以下文章:
作者:darrenzheng
链接:https://juejin.cn/post/6844903576301469704
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。