设计模式——单例,原型,生成器

简书链接:http://www.jianshu.com/p/3303f8748e09

前言

本文主要以代码形式实现每一种设计模式,算是自己的一种复习和实践。相应的代码,也会放到github上。

本篇主要讲:

  • 单例
  • 原型
  • 生成器

3.单例

概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

何时使用:
* 类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问。
* 这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。

主要用了三种方式去实现:
1.dispatch_once方式

#import <Foundation/Foundation.h>

@interface SingletonGCDObject : NSObject
+ (instancetype) sharedInstance;
@end

#import "SingletonGCDObject.h"

@implementation SingletonGCDObject

+ (instancetype) sharedInstance{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
@end

2.synchronized方式

#import <Foundation/Foundation.h>

@interface SingletonSynObject : NSObject
+ (instancetype) sharedInstance;
@end

#import "SingletonSynObject.h"

static SingletonSynObject *singletonInstrance = nil;

@implementation SingletonSynObject
+ (instancetype) sharedInstance{
    @synchronized (self) {
        if ( singletonInstrance == nil )
            singletonInstrance = [[SingletonSynObject alloc]init];
        return singletonInstrance;
    }

}
@end

3.initialize方式

#import <Foundation/Foundation.h>

@interface SingletonInitializeObject : NSObject
+ (instancetype) sharedInstance;
@end

#import "SingletonInitializeObject.h"
static SingletonInitializeObject *singletonInstrance = nil;

@implementation SingletonInitializeObject
+ (void)initialize{
    singletonInstrance = [[SingletonInitializeObject alloc]init];
}
+ (instancetype) sharedInstance{
    return singletonInstrance;
}

@end

4.原型

概念:使用原型实例指定创建对象的种类,并通过复制这个原型创建新的对象。

何时使用:
* 需要创建的对象应独立于其类型与创建方式。
* 要实例化的类是在运行时决定的。
* 不想要与产品层次相对应的工厂层次。
* 不同类的实例间的差异仅是状态的若干组合。因此复制相应数量的原型比手工实例化更加方便。
* 类不容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。

在Objective-C中,使用copy是最典型的原型的方式,而想使用copy方法,就要实现NSCopying的协议。具体代码如下:

#import <Foundation/Foundation.h>

@interface PrototypeObject : NSObject<NSCopying>
@property (nonatomic, strong)   NSString *property1;
@property (nonatomic, assign)   NSInteger property2;
@property (nonatomic, copy)     NSString *property3;
@end

#import "PrototypeObject.h"

@implementation PrototypeObject

- (id)copyWithZone:(nullable NSZone *)zone{
    PrototypeObject *object = [[[self class] allocWithZone:zone] init];
    object.property1 = self.property1;
    object.property2 = self.property2;
    object.property3 = [self.property3 copy];
    return object;
}

@end

5.生成器

概念:将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现。

何时使用:
* 需要创建涉及各种部件的复杂对象。创建对象的算法应该独立于部件的装配方式。
* 构建过程需要以不同的方式构建对象。

代码场景:
一个新的主题乐园,需要指定一系列的活动计划,包括活动第几天,住在哪里,玩什么活动的门票等。

计划类:

#import <Foundation/Foundation.h>

@interface Planner : NSObject
@property (nonatomic, assign) NSInteger date;
@property (nonatomic, copy) NSString *ticket;
@property (nonatomic, copy) NSString *hotel;
@end

计划建造者的抽象:

#import <Foundation/Foundation.h>
#import "Planner.h"

@protocol AbstractBuilder <NSObject>
- (id<AbstractBuilder>) buildPlanner;
- (id<AbstractBuilder>) addDate:(NSInteger) date;
- (id<AbstractBuilder>) addHotel:(NSString *)hotel;
- (id<AbstractBuilder>) addTicket:(NSString *)ticket;
- (Planner *) getPlanner;
@end

计划建造者的实现

#import <Foundation/Foundation.h>
#import "AbstractBuilder.h"

@interface VacationBuilder : NSObject<AbstractBuilder>

@end

#import "VacationBuilder.h"

@interface VacationBuilder(){
    Planner *_planner;
}

@end

@implementation VacationBuilder

- (id<AbstractBuilder>) buildPlanner{
    _planner = nil;
    _planner = [[Planner alloc]init];
    return self;
}
- (id<AbstractBuilder>) addDate:(NSInteger) date{
    _planner.date = date;
    return self;
}
- (id<AbstractBuilder>) addHotel:(NSString *)hotel{
    _planner.hotel = hotel;
    return self;
}
- (id<AbstractBuilder>) addTicket:(NSString *)ticket{
    _planner.ticket = ticket;
    return self;
}
- (Planner *) getPlanner{
    return _planner;
}

@end

乐园类:

#import <Foundation/Foundation.h>
#import "Planner.h"
#import "AbstractBuilder.h"

@interface VacationPark : NSObject
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder;
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder;
@end

#import "VacationPark.h"
#import "VacationBuilder.h"

@implementation VacationPark
- (Planner *)createFirstDayPlanner:(id<AbstractBuilder>)builder{
    [builder buildPlanner];
    [builder addDate:1];
    [builder addHotel:@"如家"];
    [builder addTicket:@"过山车"];
    return [builder getPlanner];
}
- (Planner *)createSecondDayPlanner:(id<AbstractBuilder>)builder{
    [builder buildPlanner];
    [builder addDate:2];
    [builder addHotel:@"汉庭"];
    [builder addTicket:@"鬼屋"];
    return [builder getPlanner];
}
@end

总结:

1.应该尽量少的使用单例,因为单例的生命周期控制会比较麻烦。尤其是当添加了撤销单例以后。参考链接Avoiding Singleton Abuse(译文:避免滥用单例)。
2.生成器与抽象工厂的对比:
生成器:
* 构建复杂对象
* 以多个步骤构建对象
* 以多种方式构建对象
* 在构建过程的最后一步返回产品
* 专注一个特定产品

抽象工厂:
* 构建简单或复杂对象
* 以单一步骤构建对象
* 以单一方式构建对象
* 立即返回产品
* 强调一套产品

参考资料

1.《Objective-C编程之道 iOS设计模式解析》
2.《Head First设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值