Bear 2: factory mode 3 brothers, have you heard?

Bear:…

The three brothers of factory pattern are simple factory pattern, factory method pattern and abstract factory pattern, which are all creative design patterns.

Didn’t you ask earlier how to design App architecture? The Design Pattern Brothers are a good example.

Why do you say that?

Bear 2: Because factory mode 3 brothers can be upgraded and downgraded according to the complexity of the function; Depending on the function changes, this extensibility is reflected, while also reducing the degree of decoupling of the code, multiple birds with one stone.

Creation pattern

Brain map structure of three factory brothers

The three factory brothers in the creation pattern are suitable for scenarios where the objects created are very similar.


Simple Factory model

The simple factory pattern violates the open and close principle of the design principle. Let’s look at the code.

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
Copy the code

Analysis:

We need to change the if else every time we add a new type, which means we may change the internal core code frequently, which violates the open and close principle.

Let’s take a look at this code.

The first point:

This code is implemented through protocol, instead of defining a parent class, using inheritance; I think protocol is more suitable for horizontal, inheritance is more suitable for vertical; The factory pattern should be better with inheritance;Copy the code

The second point:

In addition, do not use 0, 1, 2, or 3 for type. Use enumerations because they are hard to read. Our code has to be readable, our code has to be fun to look at.Copy the code

The third point:

Obviously, there will be many types of type in the future, so consider extensibility. If and else conditions here are not as good as swith statements, where switch is a more elegant and extensibility way.Copy the code

In order to facilitate the next analysis, I will not modify the code in the code display, I hope you know, if you have different views, welcome to group SOLO. The code belongs to the brother

The factory pattern

Compared to the simple factory pattern, the factory pattern just assigns the creation work to subclasses, which still does not solve the problem of the simple factory pattern violating the open and close principle.

protocol Product {} class ConcreteProductA: Product {} class ConcreteProductB: Product {} class Client { let f = Factory() } class Factory { func createProduct() -> Product? Func createProduct(type: Int) -> Product? {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 ConcreteProductACopy the code

Abstract Factory pattern

Both the simple factory pattern and the factory pattern produce the same type of product with a common parent class.

Upgrade to abstract factory mode when your product needs to use two or more.

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? Func createProductB() -> ProductB? Func createProductA(type: Int) -> ProductA? {return ConcreteFactory1().createProducta ()} else {return ConcreteFactory2().createProducta () } } func createProductB(type: Int) -> ProductB? {return ConcreteFactory1().createProductb ()} else {return ConcreteFactory2().createProductb () } } } class ConcreteFactory1: Factory { override func createProductA() -> ProductA? {/ /... Return Concreteproductoverride 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.producta (type: 0) // get ConcreteProductA1 c.f.createProductA(type: 1) // get ConcreteProductA2 c.f.createProductB(type: 0) // get ConcreteProductB1 c.f.createProductB(type: 1) // get ConcreteProductB2Copy the code

The promotion and demotion of the three brothers

  • A simple factory model is used when a single type of product is small.
  • For a single type of product with many customizations, use factory mode.
  • Use the abstract factory pattern for multiple types of products.

reference

This article code refer to the following article: author: darrenzheng links: https://juejin.cn/post/6844903576301469704 source: the nuggets copyright owned by the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.Copy the code