简单工厂、工厂方法、抽象工厂

简单工厂: 简单的switch..case 或者if 来分类创建对象 —— 具体哪一个(1个)

工厂方法: 基于简单工厂, 让子类来创建对象 —— 具体哪一个(1个)

抽象工厂: 创建一系列的对象 —— 一系列对象(多个)

它们的共同目的是通过封装对象创建的过程,减少客户端代码对具体类的依赖,从而提高系统的灵活性和可扩展性。尽管它们的目标类似,但它们的使用场景和实现方式有所不同

1. 简单工厂设计模式(Simple Factory Pattern)

简单工厂模式并不是正式的设计模式,而是常见的创建模式之一。它通过一个工厂类来根据参数创建不同的对象。

结构:

  • 工厂类:一个工厂类,它根据不同的条件创建和返回不同类型的对象。

  • 客户端:客户端通过工厂类请求对象,而无需了解具体的类名或实例化过程。

特点:

  • 单一工厂类:所有对象创建逻辑集中在一个工厂类中。

  • 无法扩展:当需要添加新的产品类时,必须修改工厂类,不符合开放封闭原则(OCP)。

示例:

class Animal {
    func speak() {}
}

class Dog: Animal {
    override func speak() {
        print("Woof")
    }
}

class Cat: Animal {
    override func speak() {
        print("Meow")
    }
}

class AnimalFactory {
    static func createAnimal(type: String) -> Animal? {
        switch type {
        case "dog":
            return Dog()
        case "cat":
            return Cat()
        default:
            return nil
        }
    }
}

// 使用
let dog = AnimalFactory.createAnimal(type: "dog")
dog?.speak()  // 输出: Woof

适用场景:

  • 当对象创建非常简单且不需要进行复杂的实例化时使用。

  • 客户端可以通过工厂获取不同类型的对象,但不需要了解这些对象的具体实现。

2. 工厂方法设计模式(Factory Method Pattern)

工厂方法模式是 简单工厂模式 的一种扩展,它通过定义一个接口来创建对象,但由子类决定实例化哪个类。每个子类实现这个工厂方法来创建具体对象。

结构:

  • 抽象工厂类:定义一个创建产品的抽象方法,子类实现该方法来生产具体产品。

  • 具体工厂类:实现抽象工厂类,创建具体产品。

  • 产品接口:定义一组产品的方法(接口)。

  • 具体产品类:实现产品接口,定义具体产品的功能。

特点:

  • 封装对象创建:客户端无需知道具体产品类,通过工厂方法得到产品对象。

  • 可扩展性强:如果需要新增产品,只需要添加新的具体工厂类,而不需要修改原有代码(符合开放封闭原则)。

示例:

protocol Animal {
    func speak()
}

class Dog: Animal {
    func speak() {
        print("Woof")
    }
}

class Cat: Animal {
    func speak() {
        print("Meow")
    }
}

protocol AnimalFactory {
    func createAnimal() -> Animal
}

class DogFactory: AnimalFactory {
    func createAnimal() -> Animal {
        return Dog()
    }
}

class CatFactory: AnimalFactory {
    func createAnimal() -> Animal {
        return Cat()
    }
}

// 使用
let dogFactory: AnimalFactory = DogFactory()
let dog = dogFactory.createAnimal()
dog.speak()  // 输出: Woof

适用场景:

  • 当需要创建的对象属于同一产品族,但具体产品可能在不同子类中实现时。

  • 客户端通过具体工厂方法来创建对象,不需要关心产品的具体类。

3. 抽象工厂设计模式(Abstract Factory Pattern)

抽象工厂模式是在 工厂方法模式 的基础上进一步扩展的,它提供了一个创建一系列相关或依赖对象的接口,而无需指定具体类。通过抽象工厂类,客户端可以创建一组相关产品,而这些产品属于同一产品族

结构:

  • 抽象工厂类:定义创建一系列产品的方法(每种产品对应一个方法)。

  • 具体工厂类:实现抽象工厂类,创建具体的产品。

  • 抽象产品类:定义一组产品的接口。

  • 具体产品类:实现产品接口,定义具体产品的功能。

  • 客户端:通过抽象工厂类获取产品,不需要关心具体实现。

特点:

  • 产品族:客户端可以选择创建一系列相关的产品(而非单一产品)。

  • 扩展性强:若需要添加新的产品族,只需添加新的具体工厂类,符合开放封闭原则。

  • 可维护性强:工厂类和产品类分离,易于管理和维护。

示例:

protocol Button {
    func render()
}

protocol ScrollBar {
    func render()
}

class MacButton: Button {
    func render() {
        print("Mac Button")
    }
}

class MacScrollBar: ScrollBar {
    func render() {
        print("Mac Scroll Bar")
    }
}

class WindowsButton: Button {
    func render() {
        print("Windows Button")
    }
}

class WindowsScrollBar: ScrollBar {
    func render() {
        print("Windows Scroll Bar")
    }
}

protocol GUIFactory {
    func createButton() -> Button
    func createScrollBar() -> ScrollBar
}

class MacFactory: GUIFactory {
    func createButton() -> Button {
        return MacButton()
    }
    
    func createScrollBar() -> ScrollBar {
        return MacScrollBar()
    }
}

class WindowsFactory: GUIFactory {
    func createButton() -> Button {
        return WindowsButton()
    }
    
    func createScrollBar() -> ScrollBar {
        return WindowsScrollBar()
    }
}

// 使用
let macFactory: GUIFactory = MacFactory()
let button = macFactory.createButton()
button.render()  // 输出: Mac Button

适用场景:

  • 当系统需要创建一系列相关的产品对象时,并且这些对象都属于同一产品族。

  • 系统需要独立于产品的创建、组合和表示。

对比总结

特性
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)

目的

封装对象创建过程,简化客户端的创建逻辑

允许子类决定实例化哪个具体类

创建一系列相关对象的接口

客户端

依赖于工厂类来创建具体的产品类

依赖于工厂接口,通过具体工厂类来创建

依赖于抽象工厂接口,创建一系列相关产品

产品数量

只能创建一种产品类型

创建单个产品类型,但可以有多个产品的子类

创建多个相关的产品(通常一对一)

扩展性

不太灵活,需要修改工厂类才能增加新产品

具有较好的扩展性,添加新产品只需新增子工厂

扩展性最强,可以轻松添加新的产品族

使用场景

对象创建比较简单,或者客户端只需创建单一对象

客户端通过工厂方法来决定具体产品创建

创建相关产品族,且不希望客户端关心具体实现

总结

  • 简单工厂模式:适用于需要通过简单的条件判断来创建少量不同类型对象的场景,通常不适合扩展。

  • 工厂方法模式:适用于需要创建不同产品的场景,但产品间有较强的继承关系,子类可以决定具体的产品。

  • 抽象工厂模式:适用于需要创建一系列相关产品(产品族)的场景,通过抽象工厂来管理多个产品的创建,具有较强的扩展性。

Last updated