设计模式-创建型

Posted 极客学伟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-创建型相关的知识,希望对你有一定的参考价值。

设计模式-创建型

创建型设计模式包含:单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式

单例模式

单例模式在开发中也是最常见的一种设计模式之一,系统原生提供的很多类的设计都采用了单例模式,例如:

FileManager.default
UserDefaults.standard
NotificationCenter.default
UIApplication.shared
URLSession.shared

其目的是为了节省内存资源并保证数据内容的一致性,需要让某些类只能创建一个实例。单例模式有如下特点:

  • 单例类只有一个实例对象
  • 单例类的实例对象由自己创建
  • 需要对外提供一个访问其实例对象的接口

在软件设计中,有关全局共享的资源数据,大型通用的管理类等都可以使用单例模式,例如登录用户的用户信息类、全局的计时器、程序的日志管理类

Swift 单例

class ClassA 
    static let share = ClassA()

Objective-C 单例

static XXClassManager *_defaultManager;
+ (instancetype)shareInstance 
    if (!_defaultManager) 
        _defaultManager = [[self alloc] init];
    
    return _defaultManager;

+ (instancetype)allocWithZone:(struct _NSZone *)zone 
    if (!_defaultManager) 
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^
            _defaultManager = [super allocWithZone:zone];
        );
    
    return _defaultManager;

- (id)copyWithZone:(NSZone *)zone
    return _defaultManager;

- (id)mutableCopyWithZone:(NSZone *)zone
    return _defaultManager;

原型模式

以一个已经创建的实例作为原型,通过复制该原型对象来创建出对象,在使用对象时,使用者无需关心对象创建的细节。在ios开发中:copy 方法就是对原型设计模式的一种实现。主要是提供了一种大量创建复杂对象的方法。

重构前

import Foundation
class Computer 
    var cpu: String
    var host: String
    var screen: String
    var uuid: String
    init(cpu: String, host: String, screen: String) 
        self.cpu = cpu
        self.host = host
        self.screen = screen
        self.uuid = UUID().uuidString
    
    func logUUID() 
        print(uuid)
    

let computer1 = Computer(cpu: "Intel core i7 7700K", host: "GY088-GDF-60", screen: "3008 x 1692")
computer1.logUUID()

此时若希望创建一台相同配置的电脑则只能使用重复的创建方法

let computer2 = Computer(cpu: "Intel core i7 7700K", host: "GY088-GDF-60", screen: "3008 x 1692")

重构后

import Foundation
class Computer 
    ...
    
    func copy() -> Computer 
        return Computer(cpu: self.cpu, host: self.host, screen: self.screen)
    

新增一个 copy() 方法,此时再创建相同配置的电脑只需调用原型的 copy() 方法即可,省去了配件的创建过程。
使用原型模式,一旦第一个对象被创建,后面的对象创建都将变得非常容易。其中,作为模板对象被称为原型,创建出来的对象拥有和模板对象一致的属性和方法。

工厂方法模式

工厂方法设计模式注重于将对象的创建过程封闭起来,通过定义抽象的工厂接口和商品接口来隐藏负责对象创建的具体类

对上述 Computer 类进行重构

重构后

enum Level 
    case low
    case high

protocol ComputerFactoryProtol 
    static func getComputer(level: Level) -> ComputerProtol

protocol ComputerProtol 
    var cpu: String  get 
    var host: String  get 
    var screen: String  get 
    var uuid: String  get 
    func logUUID()

class Computer: ComputerProtol 
    var cpu: String
    var host: String
    var screen: String
    var uuid: String
    init(cpu: String, host: String, screen: String) 
        self.cpu = cpu
        self.host = host
        self.screen = screen
        self.uuid = UUID().uuidString
    
    func logUUID() 
        print(uuid)
    

class ComputerFactory: ComputerFactoryProtol 
    static func getComputer(level: Level) -> ComputerProtol 
        switch level 
        case .low:
            return Computer(cpu: "Intel core i5 3300K", host: "GY088-GDF-10", screen: "1920 x 1080")
        case .high:
            return Computer(cpu: "Intel core i7 7700K", host: "GY088-GDF-60", screen: "3008 x 1692")
        
    

引入的 ComputerFactory 即工厂设计模式的具体体现,外界不再指明具体的配置信息,只需要根据 level 即可创建指定配置的 Computer,
创建高配电脑,例如:

let computer3 = ComputerFactory.getComputer(level: .high)

如果新增加了一种创建方式完全不同的计算机,我们只需要新建一个遵守 ComputerProtol 的计算机类,之后在 ComputerFactory 中统一处理这种新增的计算机类型即可,对使用者完全隐藏。

抽象工厂模式

抽象工厂是对工厂模式的一种升级,核心思路是为各种类型的对象提供一组统一的创建接口,使用者无需关心这些对象具体是如何创建的。

还是上述代码,若我们工厂方法即生产 Computer 又可以生产 TV

重构后

enum Level 
    case low
    case high

protocol ComputerFactoryProtol 
    static func getComputer(level: Level) -> ComputerProtol
    static func getTV() -> TVProtol

protocol TVProtol 
    var name: String  get 
    func logName()

class TV: TVProtol 
    var name: String
    init(name: String) 
        self.name = name
    
    func logName() 
        print(self.name)
    

protocol ComputerProtol 
    ...

class Computer: ComputerProtol 
    ...    

class ComputerFactory: ComputerFactoryProtol 
    static func getTV() -> TVProtol 
        return TV(name: "海尔")
    
    static func getComputer(level: Level) -> ComputerProtol 
        ...
    

重构后工厂类可以创建不同的对象,对于使用者无需关心创建的细节,抽象工厂将对象的创建和使用进行了完全分离。

建造者模式

建造者模式用于复杂对象的创建,使代码聚合性更强,逻辑更加清晰。建造者模式通常与工程模式配合使用,工厂着重于对象的创建,建造者着重于创建复杂对象过程中组成对象的每一部分创建和最终组装。
核心在于将复杂的对象拆解成多个简单对象,通过一步步构建简单对象最终组合成复杂对象。

重构后

enum Foodtype 
    case a
    case b

enum Drink 
    case cola
    case juice

enum Staple 
    case hamburger
    case chickenRoll

class FoodPackage 
    var drink: Drink?
    var staple: Staple?

class BuildA 
    var foodPackage = FoodPackage()
    func build() -> FoodPackage 
        foodPackage.drink = .cola
        foodPackage.staple = .hamburger
        return foodPackage
    

class BuildB 
    var foodPackage = FoodPackage()
    func build() -> FoodPackage 
        foodPackage.drink = .juice
        foodPackage.staple = .chickenRoll
        return foodPackage
    

class FoodFactory 
    static func buildFood(type: Foodtype) -> FoodPackage 
        switch type 
        case .a:
            return BuildA().build()
        case .b:
            return BuildB().build()
        
    

let foodPackage = FoodFactory.buildFood(type: .a)

其中,一个完整的套餐对象由饮料对象、主食对象组成,FoodFactory 为工厂方法,其中根据套餐类型创建不同的套餐对象,具体的套餐对象的组成则是由 BuildABuildB 来完成。 BuildABuildB 是建造者模式的核心类,充当建造者的角色。

以上是关于设计模式-创建型的主要内容,如果未能解决你的问题,请参考以下文章

新食堂的早餐搭配 (二分做法)

新食堂的早餐搭配 (二分做法)

设计模式——建造者模式实例

力扣 - LCP 18. 早餐组合

力扣 - LCP 18. 早餐组合

Golang 策略设计模式