设计模式(二)抽象工厂模式

907 阅读4分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

摘要

抽象工厂模式首先定义创建的对象和要实现的函数,子类通过遵守的方式,在基类的框架下去实现处理等。子类和基类之间存在一种继承关系,同时子类之间相互兼容,是一种比较灵活的设计模式。

抽象工厂模式是创建型模式,通过它可以创建一系列相关对象,并不需要指定具体的类。它有声明的基类,也有继承基类的具体子类。一般看到子类有重新实现基类声明的方法,就属于抽象工厂模式

抽象工厂模式和工厂模式在构架实现的时候是有一些相似的地方,所以容易产生混淆。首先两种模式都是创建型模式,也就是一定有创建对象的方法,但是在构架思路上是有不同的,工厂方法就是不同的子类有自己的方法实现,之间是相互独立的,而且对外是不暴露子类对象。抽象工厂子类都基类是有继承关系的,之间是可以互相兼容的,对外是暴露子类对象,去做相关处理。

接下来,通过实现过程,在来理解上面的文字。

首先创建一个抽象工厂模式的一些,声明两个创建不同产品的函数,后面就可以使用 AbstractFactory 的实例得到两个不同的产品对象:

protocol AbstractFactory {
    func createProductA() -> AbstractProductA
    func createProductB() -> AbstractProductB
}

接下来创建一个 class 的子类继承上面的基类,实现协议中声明的方法,返回的产品对象可以是分别继承抽象产品协议(AbstractProductAAbstractProductB)的具体产品对象。

class ConcreteFactory1: AbstractFactory {
    func createProductA() -> AbstractProductA {
        return ConcreteProductA1()
    }
    
    func createProductB() -> AbstractProductB {
        return ConcreteProductB1()
    }
}

再创建一个具体的工厂类继承基类,实现协议中的方法等:

class ConcreteFactory2: AbstractFactory {
    func createProductA() -> AbstractProductA {
        return ConcreteProductA2()
    }
    
    func createProductB() -> AbstractProductB {
        return ConcreteProductB2()
    }
}

之后还是用 protocol 来创建抽象产品,上面的代码可以看到抽象产品协议有 A 和 B 两种,每一种都有两个不同的子类继承。这里先创建抽象产品协议,声明方法:

protocol AbstractProductA {
    func usefulFunctionA() -> String
}
​
protocol AbstractProductB {
    func usefulFunctionB() -> String
    func anotherUsefulFunctionB(collaborator: AbstractProductA) -> String
}

协议里面只声明的方法用作示例,和抽象产品相关的方法都要在协议中声明。看 anotherUsefulFunctionB 方法中,传入的参数类型是 AbstractProductA。也就是抽象产品类直接可以组合处理。

接下来创建子类继承这些抽象的产品类,因为代码相似,这里只展示 ConcreteProductA1的创建代码:

class ConcreteProductA1: AbstractProductA {
    func usefulFunctionA() -> String {
        return "this is product A 1"
    } 
}
​
class ConcreteProductB1: AbstractProductB {
    
    func usefulFunctionB() -> String {
        return "this is product B 1"
    }
    
    func anotherUsefulFunctionB(collaborator: AbstractProductA) -> String {
        let result = collaborator.usefulFunctionA()
        return "this is product B 1 and (result)"
    } 
}

剩下的两个子类和上面实现一样,就不浪费篇幅。这里要着重看一下 anotherUsefulFunctionB 函数中使用 A 类产品,直接使用其抽象类型,不需要去确定到具体的子类的产品类型。

A 类和 B 类可以组合处理,比如上面的示例,B 类方法中调用 A 类对象。

最后就是调用并实现,创建 Client 类,实现一些方法代码:

class Client {
        
    static func someClientCode(factory: AbstractFactory) {
        let productA = factory.createProductA()
        let productB = factory.createProductB()
        
        print(productB.usefulFunctionB())
        print(productB.anotherUsefulFunctionB(collaborator: productA))
    }
}

someClientCode 函数的参数使用抽象工厂类,继承该抽象工厂类的子类都可以作为实参传递进来:

Client.someClientCode(factory: ConcreteFactory1())
Client.someClientCode(factory: ConcreteFactory2())

到这里就已经完整实现了抽象工厂模式,如果看之前对工厂方法的文章,看到这里,似乎也是没法很好区分看这两个模式。Swift 实现上,都是通过 protocol 完成的,所以就更难区分。这里建议不要太较真,先要有个印象,等再接触一些其他创建型模式之后再回过头来看一下。

题外话

设计模式比较抽象,需要多温习,多实践,才能很好吸收。所以本文会时时更新,力求把抽象说的更具体。没有考虑到的地方,可以评论区和我留言讨论。