设计模式到底该怎么用

Posted by syea on February 5, 2018

单例模式

  • 运用场景

    单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:

    1. 需要频繁实例化然后销毁的对象。
    2. 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
    3. 有状态的工具类对象。
    4. 频繁访问数据库或文件的对象。
  • 运用方式
    单例的写法有很多种,一般写的时候都会注意防止在多线程情况下,对象被创建多次。

  • 优缺点
    优点:
    单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
    如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
    单例模式因为类控制了实例化过程,所以类可以更加灵活修改实例化过程。
    缺点:
    单例对象一旦建立,对象指针是保存在静态区的,单例对象在堆中分配的内存空间,会在应用程序终止后才会被释放。
    单例类无法继承,因此很难进行类的扩展。
    单例不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
+ (instancetype)sharedInstance
{
    static id sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[XXX alloc] init];
    });
    return sharedInstance;
}
static id <#name#>;

+ (id)allocWithZone:(struct _NSZone *)zone
{
    @synchronized(self) {
        if (<#name#> == nil) {
            <#name#> = [super allocWithZone:zone];
        }
    }
    return <#name#>;
}

+ (instancetype)share<#name#>
{
    if (<#name#> == nil) {              //这个判断防止加多把锁
        @synchronized(self) {
            if (<#name#> == nil) {      //这个判断防止创建多次
                <#name#> = [[super alloc] init];
            }
        }
    }
    return <#name#>;
}

原型模式

  • 运用场景

    通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

  • 运用方式

    本质上就是copyclone。顺便提一下浅复制和深复制,浅复制只复制指向内存资源的指针,深复制不仅复制指向内存资源的指针还复制了一份一样的内存资源。

工厂模式&抽象工厂模式

  • 运用场景

    定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到子类。
    1.编译时无法准确预期要创建的对象的类
    2.类想让子类决定在运行时创建什么

  • 运用方式
    一般在有很多类似的类的时候使用这种设计模式
    举个🌰:
    做过一个电商项目,其中的店铺有4种类型,这里称为a.b.c.d。
  1. 简单工厂模式↓
    • 第一种写法,一种写一个创建方法,扩展时需要新增一个类,新增一个创建方法,支持个性化参数
       AShop *aShop = [ShopFactory creatAShop];
       BShop *bShop = [ShopFactory creatBShop];
       CShop *cShop = [ShopFactory creatCShop];
       DShop *dShop = [ShopFactory creatDShopWithName:@"dream"];
      
    • 第二种写法,统一一个创建方法,扩展时需要新增一个类,修改创建方法,但是这种写法不支持个性化参数
       AShop *aShop = [ShopFactory creatShopWithType:ShopTypeA];
       BShop *bShop = [ShopFactory creatShopWithType:ShopTypeB];
       CShop *cShop = [ShopFactory creatShopWithType:ShopTypeC];
       DShop *dShop = [ShopFactory creatShopWithType:ShopTypeD];
      
    • 第三种写法是第二种的改进,运用了反射,扩展时需要新增一个类,不需要修改创建方法,同样不支持个性化参数
       AShop *aShop = [ShopFactory creatShopWithClass:[aShop class]];
       BShop *bShop = [ShopFactory creatShopWithClass:[bShop class]];
       CShop *cShop = [ShopFactory creatShopWithClass:[cShop class]];
       DShop *dShop = [ShopFactory creatShopWithClass:[dShop class]];
      
  2. 工厂模式↓
    扩展时需要新增一个类并继承父类的方法
     ShopFactory *shopFactory = [[AShopFactory alloc] init];
     AShop *aShop = [shopFactory creatShop];
    
  3. 现在给Shop类加上方法,卖 x 物品与卖 y 物品。
    抽象工厂模式↓
    扩展时需要新增一个 factory,继承父类方法。
     // `sellXGoods` `sellYGoods` 是父类 `ShopFactory` 的方法
     ShopFactory *shopFactory = [[AShopFactory alloc] init];
     AShop *aShop = [shopFactory creatShop];
     [aShop sellXGoods];
     [aShop sellYGoods];