抛开那些吹嘘的高大上东西,简单的开发设计模式,解决日常工作中实际的业务开发!!!

工厂模式

背景

image

protocol Product {}
class ConcreteProductA: Product {}
class ConcreteProductB: Product {}

class Client {
    func createProduct(type: Int) -> Product {
        if type == 0 {
            return ConcreteProductA()
        } else {
            return ConcreteProductB()
        }
    }
}

let c = Client()
c.createProduct(type: 0) // get ConcreteProductA


为了得到产品A,调用者Client同时依赖Product,ConcreteProductA,ConcreteProductB,并亲自写一个创建产品的方法。 那么,每当需求新增一个产品,就要改动到调用方Client,繁琐,故将创建代码抽离出去,简单工厂孕育而生。

简单工厂 Simple Factory

image

简单工厂做了一件事,把Client要做的创建工作,挪到另一个类里


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

Factory 代替了 Client 对具体Product 的依赖,如此,当需求变化的时候, 不再需要改动调用方,这有所进步。 但是!无法避免的是, 每次变动都要在createProduct的方法内部新增一个if-else分支,违背了开闭原则 。由此,引入另一个模式。

工厂方法

定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

image


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

对工厂方法实现,有众多不同的解法。 例如, Factory 只保留一个createProduct让子类实现, 让Client来选择生成哪个具体工厂实例; 或是引入一个FactoryMaker 中间层, 作为生产工厂的“简单工厂”。 这里采用的方法是,Factory既作为工厂父类,让具体工厂决定生成什么产品,又作为接口类,让Client可以通过 依赖注入选择特定工厂。这样做的目的是,在不引入新的中间层的情况下,最小化Client 的依赖。

工厂方法在简单工厂基础上做了两件事:

多了一层抽象,把生产产品的工作延迟到子类执行
把 “选择如何生产产品的工作” 转化为 “选择让哪个具体工厂生产”

工厂方法贡献在于,虽不让完美避免对一个if-else扩展,但是这个扩展规模被极大限制住了(只需new一个类)

工厂方法着重点是解决单一产品线的派生问题,如果有多个相关产品线呢?

抽象工厂

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

image


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

当我们有两个相关的产品线ProductA,ProductB,(螺丝螺母),它们派生出ProductA1,ProductB1 和 ProductA2, ProductB2, 前者我们由工厂ConcreteFactory1来制作,后者由ConcreteFactory2 来制作。

对于 Client 来说, 只需知道有一个抽象的工厂能同时生产ProductA,ProductB就行了,那就是图中的Factory。

那个抽象的Factory是通过“工厂方法”模式把构造过程延迟到子类执行的,也就是说,抽象工厂是建立在工厂方法的基础上的模式。

抽象工厂换句话说,就是多个产品线需要绑定在一起,形成一个抽象的综合工厂,由具体的综合工厂来批量实现“工厂方法”的一种更“高级”的模式。

这些工厂模式并不是割裂的存在,而是一个递进的思想

Builder 建造者模式

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
建造者模式,就是把产品内部的组件生产工作抽离出去,是一个类自身的属性(组件)构造过程。
背景:有复杂、规则模块的对象生成流程

image


struct Builder {
    var partA: String
    var partB: String
}

struct Product {
    var partA: String
    var partB: String
    init(builder: Builder) {
        partA = builder.partA
        partB = builder.partB
    }
}

// 通过builder完成产品创建工作
let b = Builder(partA: "A", partB: "B")
// 这样产品只需要一个builder就可以完成制作
let p = Product(builder: b)
让Product的生成由自己发起,但是它的组件(属性)全部委托给Builder来实现,它只需要依赖一个Builder就完成了自身的生产工作。

Prototype 原型模式

原型模式让你有了一个可以源源不断自我赋值的类
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象

原型模式要求实现一个返回你自己的新对象的方法,实现了 深拷贝。

image


protocol Prototype {
    func clone() -> Prototype
}

struct Product: Prototype {
    var title: String
    func clone() -> Prototype {
        return Product(title: title)
    }
}

let p1 = Product(title: "p1")
let p2 = p1.clone()
(p2 as? Product)?.title // OUTPUT: p1

Singleton 单例模式

唯一存在,被所有人直接访问
保证一个类仅有一个实例, 并提供一个访问它的全局访问点
单例模式常见的应用是例如数据库,网络框架的全局访问点

单例其实就是变种的原型模式,只不过原型每次返回的是一个拷贝

image


//简单实现
class Singleton {
    static let sharedInstance = Singleton()
    private init() {
        // 用private防止被new
    }
}
let s  = Singleton.sharedInstance
let s2 = Singleton() // ERROR: initializer is inaccessible due to 'private' protection level

//完整实现
class Singleton {
    static var singleton: Singleton? = nil
    private init() {}
    static func sharedInstance() -> Singleton {
        if singleton == nil {
            singleton = Singleton()
        }
        return singleton!
    }
}

let s = Singleton.sharedInstance()
let s2 = Singleton() // ERROR: initializer is inaccessible due to 'private' protection level


各位小伙伴,在日常开发中如果业务不是很复杂这样的简单开发模式设计思想对你来说够用了也或者根本会用不到但是对你也可以作为知识上的累积,今天就分享了一些在公司日常开发用到的一些简单的开发模式,希望对你有所帮助

青山不改,绿水长流,2022年!新年快乐!

posted @ 2022-02-03 21:01  一眼万年的星空  阅读(40)  评论(0编辑  收藏  举报