读《大话设计模式》三

行为型模式

迭代器模式

模式动机

针对不同的需要,可能还要以不同的方式遍历整个聚合对象,但是我们并不希望在聚合对象的抽象层接口中充斥着各种不同遍历的操作。
怎样遍历一个聚合对象,又不需要了解聚合对象的内部结构,还能够提供多种不同的遍历方式,这就是迭代器模式的模式动机。

模式定义

提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

模式结构

模板方法模式包含如下角色:

  • Aggregate: 聚集抽象类
  • ConcreteAggregate: 具体聚集类
  • Iterator: 迭代抽象类
  • ConcreteIterator: 具体迭代器类
读《大话设计模式》三_第1张图片
迭代器模式类图
时序图

源码

行为型

命令模式

模式动机

在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。

命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。

模式定义

命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

模式结构

命令模式包含如下角色:

  • Command: 抽象命令类
  • ConcreteCommand: 具体命令类
  • Invoker: 调用者
  • Receiver: 接收者
  • Client:客户类


    读《大话设计模式》三_第2张图片
    命令模式类图
时序图
读《大话设计模式》三_第3张图片
命令模式时序图
源码
//使用示例
    //waiter用于接收各种类型的order。waiter是请求接收者。
    //接收不同customer产生的不同order,并且都存入waiter这个接受者中,type表示不同类型的order。
    HCDWaiter *waiter = [[HCDWaiter alloc]init];
    
    //顾客一
    HCDCustomr *customer = [[HCDCustomr alloc]init];
    HCDOrder *customerOrder1 = [customer pushOrderWithString:@"顾客一要十串羊肉" type:orderTypeMutton];
    HCDOrder *customerOrder2 = [customer pushOrderWithString:@"顾客一要十串鸭肉" type:orderTypeDuck];
    [waiter addOrder:customerOrder1];
    [waiter addOrder:customerOrder2];
    
    //顾客二
    HCDCustomr *customer1 = [[HCDCustomr alloc]init];
    HCDOrder *customer1Order1 = [customer1 pushOrderWithString:@"顾客二要二十串鸡肉" type:orderTypeChicken];
    HCDOrder *customer1Order2 = [customer1 pushOrderWithString:@"顾客二要二十串鸭肉" type:orderTypeDuck];
    [waiter addOrder:customer1Order1];
    [waiter addOrder:customer1Order2];
    [waiter deleteOrder:customer1Order2];
    
    //waiter发送order,背后有一个HCDWorker这个单列作为行为实现者来处理具体的order。命令接收完毕,开始发送命令。
    [waiter notifyOrder];
//HCDCustomr.m
@implementation HCDCustomr

-(HCDOrder *)pushOrderWithString:(NSString *)string type:(orderType)type{
    HCDOrder *order = nil;
    switch (type) {
        case orderTypeMutton:
            order = [[HCDMuttonOrder alloc]initWithOrderString:string];
            break;
        case orderTypeChicken:
            order = [[HCDChickenOrder alloc]initWithOrderString:string];
            break;
        case orderTypeDuck:
            order = [[HCDDuckOrder alloc]initWithOrderString:string];
            break;
    }
    return order;
}
@end
//HCDWaiter.m
@implementation HCDWaiter

-(instancetype)init{
    self = [super init];
    if (self) {
        _orderList = [NSMutableArray array];
    }
    return self;
}
-(void)addOrder:(HCDOrder *)order{
    NSLog(@"添加Order");
    [self.orderList addObject:order];
}
-(void)deleteOrder:(HCDOrder *)order{
    NSLog(@"取消Order");
    [self.orderList removeObject:order];
}
/*
 命令接收完毕,开始执行命令
 */
-(void)notifyOrder{
    NSLog(@"====开始执行Order===");
    for (HCDOrder *order in self.orderList) {
        [order executeOrder];
    }
}
@end
//HCDOrder.h
@interface HCDOrder : NSObject

@property(nonatomic,copy)NSString *orderString;

-(instancetype)initWithOrderString:(NSString *)orderString;
//执行命令
-(void)executeOrder;

@end

//HCDMuttonOrder.m
@implementation HCDMuttonOrder

-(void)executeOrder{
    NSLog(@"烤羊");
    [[HCDWorker sharedWorker] doMuttonWork:self.orderString];
}
@end

//HCDChickenOrder.m
@implementation HCDChickenOrder

-(void)executeOrder{
    NSLog(@"烤鸡");
    [[HCDWorker sharedWorker] doChickenWork:self.orderString];
}

@end

//HCDDuckOrder.m
@implementation HCDDuckOrder

-(void)executeOrder{
    NSLog(@"烤鸭");
    [[HCDWorker sharedWorker] doChickenWork:self.orderString];
}

@end 
//HCDWorker.h
@interface HCDWorker : NSObject

+(instancetype)sharedWorker;

-(void)doMuttonWork:(NSString *)work;

-(void)doChickenWork:(NSString *)work;

-(void)doDuckWork:(NSString *)work;

@end

中介者模式

模式动机
  • 在用户与用户直接聊天的设计方案中,用户对象之间存在很强的关联性,将导致系统出现如下问题:
  • 系统结构复杂:对象之间存在大量的相互关联和调用,若有一个对象发生变化,则需要跟踪和该对象关联的其他所有对象,并进行适当处理。
  • 对象可重用性差:由于一个对象和其他对象具有很强的关联,若没有其他对象的支持,一个对象很难被另一个系统或模块重用,这些对象表现出来更像一个不可分割的整体,职责较为混乱。
  • 系统扩展性低:增加一个新的对象需要在原有相关对象上增加引用,增加新的引用关系也需要调整原有对象,系统耦合度很高,对象操作很不灵活,扩展性差。
  • 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责。
  • 对于一个模块,可能由很多对象构成,而且这些对象之间可能存在相互的引用,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式,这就是中介者模式的模式动机。
模式定义

中介者模式(Mediator Pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。它是一种对象行为型模式。

模式结构

中介者模式包含如下角色:

  • Mediator: 抽象中介者
  • ConcreteMediator: 具体中介者
  • Colleague: 抽象同事类
  • ConcreteColleague: 具体同事类


    读《大话设计模式》三_第4张图片
    中介者模式类图
时序图
读《大话设计模式》三_第5张图片
中介者模式时序图
源码
    //使用示例
    ConcreteMediator *mediator = [[ConcreteMediator alloc] init];
    
    //初始化并且让两个同事有相同的中介者对象
    ConcreteColleague1 *c1 = [[ConcreteColleague1 alloc] initWithMediator:mediator];
    ConcreteColleague2 *c2 = [[ConcreteColleague2 alloc] initWithMediator:mediator];
    
    //给中介者对象绑定两个要交互的同事对象
    mediator.colleague1 = c1;
    mediator.colleague2 = c2;
    
    [c1 send:@"吃过饭了吗?"];
    [c2 send:@"没有呢,你打算请客?"];
//Mediator.h
@class Colleague;
@interface Mediator : NSObject

@property (nonatomic, strong) Colleague *colleague1;
@property (nonatomic, strong) Colleague *colleague2;

-(void)send:(NSString *)message colleague:(Colleague *)colleague;

@end
//ConcreteMediator.m
@implementation ConcreteMediator

-(void)send:(NSString *)message colleague:(Colleague *)colleague{
    if (colleague == self.colleague1) {
        [self.colleague2 notify:message];
    }else{
        [self.colleague1 notify:message];
    }
}

@end
//Colleague.h
@class Mediator;
@interface Colleague : NSObject

@property(nonatomic, strong) Mediator *mediator;

-(instancetype)initWithMediator:(Mediator *)mediator;

-(void)notify:(NSString *)message;

-(void)send:(NSString *)message;

@end
//ConcreteColleague1.m
@implementation ConcreteColleague1

-(instancetype)initWithMediator:(Mediator *)mediator{
    self = [super init];
    if (self) {
        self.mediator = mediator;
    }
    return self;
}

-(void)send:(NSString *)message{
    NSLog(@"同事1发送了信息");
    [self.mediator send:message colleague:self];
}

-(void)notify:(NSString *)message{
    NSLog(@"%@%@",@"同事1得到消息:", message);
}

@end
//ConcreteColleague2.m
@implementation ConcreteColleague2

-(instancetype)initWithMediator:(Mediator *)mediator{
    self = [super init];
    if (self) {
        self.mediator = mediator;
    }
    return self;
}

-(void)send:(NSString *)message{
    NSLog(@"同事2发送了信息");
    [self.mediator send:message colleague:self];
}

-(void)notify:(NSString *)message{
    NSLog(@"%@%@",@"同事2得到消息", message);
}

@end

观察者模式

模式动机

建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。

模式定义

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式是一种对象行为型模式。

模式结构

观察者模式包含如下角色:

  • Subject: 目标
  • ConcreteSubject: 具体目标
  • Observer: 观察者
  • ConcreteObserver: 具体观察者


    读《大话设计模式》三_第6张图片
    观察者模式类图
时序图
读《大话设计模式》三_第7张图片
观察者模式时序图
源码
//使用示例
- (void)viewDidLoad {
    [super viewDidLoad];
    
    HCDServiceCenter *serviceCenter = [[HCDServiceCenter alloc] init];
    
    [serviceCenter addDelegate:self.nbaobserver];
    [serviceCenter addDelegate:self.stockobserver];
    [serviceCenter addDelegate:self.gameObserver];
    
    NSLog(@"秘书通知:老板回来了,大家赶紧撤"); 
    [serviceCenter notifyServiceDelegate:@selector(update)
                                 perform:^(id responder) {
                                     [responder update];
    }];
}

#pragma mark - getter & setter

-(HCDNBAObserver *)nbaobserver {
    if (!_nbaobserver) {
        _nbaobserver = [[HCDNBAObserver alloc] init];
    }
    return _nbaobserver;
}

-(HCDStockObserver *)stockobserver {
    if (!_stockobserver) {
      _stockobserver = [[HCDStockObserver alloc] init];
    }
    return _stockobserver;
}

-(HCDGameObserver *)gameObserver {
    if (!_gameObserver) {
        _gameObserver = [[HCDGameObserver alloc] init];
    }
    return _gameObserver;
}
//HCDServiceCenter.h
@interface HCDServiceCenter : NSObject

@property(nonatomic, strong, readonly) NSHashTable *responders;

- (instancetype)initWithNotifyQueue:(dispatch_queue_t)notifyQueue;

- (void)addDelegate:(id)delegate;

- (void)removeDelegate:(id)delegate;

- (void)notifyServiceDelegate:(SEL)aSelector
                      perform:(void (^)(id responder))perform;

@end
//HCDServiceCenter.m
#define LOCK(...) dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); \
__VA_ARGS__; \
dispatch_semaphore_signal(_lock);

@interface HCDServiceCenter()

@property(nonatomic, strong) dispatch_queue_t notifyQueue;

@property(nonatomic, strong) NSHashTable *responders;

@end

@implementation HCDServiceCenter {
    dispatch_semaphore_t _lock;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.responders = [NSHashTable weakObjectsHashTable];
        self.notifyQueue = dispatch_get_main_queue();
        _lock = dispatch_semaphore_create(1);
    }
    return self;
}

- (instancetype)initWithNotifyQueue:(dispatch_queue_t)notifyQueue {
    self = [super init];
    if (self) {
        self.responders = [NSHashTable weakObjectsHashTable];
        self.notifyQueue = notifyQueue;
    }
    return self;
}

- (void)addDelegate:(id)delegate { 
    LOCK([self.responders addObject:delegate]);
}

- (void)removeDelegate:(id)delegate {
    LOCK([self.responders removeObject:delegate]); 
}

- (void)notifyServiceDelegate:(SEL)aSelector
                      perform:(void (^)(id responder))perform {
    dispatch_async(self.notifyQueue, ^{
        NSArray *responders = self.responders.allObjects;
        for (id responder in responders) {
            if ([responder respondsToSelector:aSelector]) {
                @try {
                    perform(responder);
                }
                @catch (NSException *exception) {
                    NSLog(@"catch notifyServiceDelegate exception: %@", exception);
                }
            }
        }
    });
}

@end
//HCDObserver.h
@protocol HCDObserver 

@optional
- (void)update;

@end

//HCDStockObserver.h
@interface HCDStockObserver : NSObject

@end

//HCDNBAObserver.h
@interface HCDNBAObserver : NSObject

@end

//HCDGameObserver.h
@interface HCDGameObserver : NSObject

@end

状态模式

模式动机

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于负责时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

模式定义

允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。状态模式是一种对象行为型模式。

模式结构

状态模式包含如下角色:

  • Context: 环境类
  • State: 抽象状态类
  • ConcreteState: 具体状态类


    读《大话设计模式》三_第8张图片
    状态模式类图
时序图
读《大话设计模式》三_第9张图片
状态模式时序图
源码
    //使用示例
    HCDWork *work = [[HCDWork alloc]init];
    work.hour = 9;
    [work writeProgram];
    
    work.hour = 10;
    [work writeProgram];
    
    work.hour = 12;
    [work writeProgram];
    
    work.hour = 13;
    [work writeProgram];
    
    work.hour = 14;
    [work writeProgram];
    
    work.hour = 17;
    [work writeProgram];
    
    work.finished = NO;
    [work writeProgram];
    
    work.hour = 19;
    [work writeProgram];
    
    work.hour = 22;
    [work writeProgram];
//HCDWork.h
@interface HCDWork : NSObject

@property(nonatomic, assign) CGFloat hour;

@property(nonatomic, assign) BOOL finished;

- (void)writeProgram;

- (void)changeState:(HCDState *)state;

@end
//HCDWork.m
@interface HCDWork()

@property (nonatomic, strong) HCDState *state;

@end

@implementation HCDWork

- (instancetype)init{
    self = [super init];
    if (self) {
        self.state = [[HCDForenoonState alloc]init];
    }
    return self;
}

- (void)writeProgram {
    [self.state writeProgram:self];
}

- (void)changeState:(HCDState *)state {
    self.state = state;
}

@end
//HCDProtocol.h
@class HCDWork;
@protocol HCDProtocol 

@optional
- (void)writeProgram:(HCDWork *)work;

@end
//HCDState.h
@interface HCDState : NSObject

@end
//HCDForenoonState.m
@implementation HCDForenoonState

-(void)writeProgram:(HCDWork *)work{
    if (work.hour < 12) {
         NSLog(@"当前时间:{%.f}点,上午工作,精神百倍", work.hour);
    }else{
        HCDNoonState *noonState = [[HCDNoonState alloc] init];
        [work changeState:noonState];
        [work writeProgram];
    }
}
@end
//HCDNoonState.m
@implementation HCDNoonState

-(void)writeProgram:(HCDWork *)work{
    if (work.hour < 13) {
        NSLog(@"当前时间:{%.f}点,饿了,午饭;犯困,午休", work.hour);
    } else {
        HCDAfternoonState *afternoonState = [[HCDAfternoonState alloc] init];
        [work changeState:afternoonState];
        [work writeProgram];
    }
}
@end
//HCDAfternoonState.m
@implementation HCDAfternoonState

-(void)writeProgram:(HCDWork *)work{
    if (work.hour < 17) {
        NSLog(@"当前时间:{%.f}点,下午状态还不错,继续努力", work.hour);
    } else {
        HCDEventState *eventState = [[HCDEventState alloc] init];
        [work changeState:eventState];
        [work writeProgram];
    }
}
@end
//HCDEventState.m
@implementation HCDEventState

-(void)writeProgram:(HCDWork *)work{
    if (work.finished) {
        HCDRestState *restState = [[HCDRestState alloc] init];
        [work changeState:restState];
        [work writeProgram];
    } else {
        if (work.hour < 21) {
            NSLog(@"当前时间:{%.f}点,加班哦,疲累之极", work.hour);
        } else {
            HCDSleepState *sleepState = [[HCDSleepState alloc] init];
            [work changeState:sleepState]; 
            [work writeProgram];
        }
    }

}

@end
//HCDSleepState.m
@implementation HCDSleepState

- (void)writeProgram:(HCDWork *)work {
    NSLog(@"当前时间:{%.f}点,不行了,睡着了", work.hour);
}
@end
//HCDRestState.m
@implementation HCDRestState

- (void)writeProgram:(HCDWork *)work {
    NSLog(@"当前时间:{%.f}点,下班回家了", work.hour);
}
@end

策略模式

模式动机
  • 完成一项任务,往往可以有多种不同的方式,每一种方式称为一个策略,我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。
  • 在软件开发中也常常遇到类似的情况,实现某一个功能有多个途径,此时可以使用一种设计模式来使得系统可以灵活地选择解决途径,也能够方便地增加新的解决途径。
  • 为了解决这些问题,可以定义一些独立的类来封装不同的算法,每一个类封装一个具体的算法,在这里,每一个封装算法的类我们都可以称之为策略(Strategy),为了保证这些策略的一致性,一般会用一个抽象的策略类来做算法的定义,而具体每种算法则对应于一个具体策略类。
模式定义

定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

模式结构

策略模式包含如下角色:

  • Context: 环境类
  • Strategy: 抽象策略类
  • ConcreteStrategy: 具体策略类
读《大话设计模式》三_第10张图片
策略模式类图
时序图
读《大话设计模式》三_第11张图片
策略模式时序图
源码
    //使用示例
    HCDCashContext *context = [[HCDCashContext alloc] initWithCashType:HCDCashTypeNormal];
    NSLog(@"结果是%f",[context getResult:100]);

    HCDCashContext *contextReturn = [[HCDCashContext alloc] initWithCashType:HCDCashTypeReturn];
    NSLog(@"结果是%f",[contextReturn getResult:100]);
    
    HCDCashContext *contextRobate = [[HCDCashContext alloc] initWithCashType:HCDCashTypeRobate];
    NSLog(@"结果是%f",[contextRobate getResult:100]);
//HCDCashContext.h
typedef NS_ENUM(NSInteger, HCDCashType){
    HCDCashTypeNormal = 0,
    HCDCashTypeRobate,
    HCDCashTypeReturn
};

@interface HCDCashContext : NSObject 

-(instancetype)initWithCashType:(HCDCashType)type;

-(CGFloat)getResult:(CGFloat)money;

@end
//HCDCashContext.m
@interface HCDCashContext()

@property (nonatomic, strong) id cash;

@end

@implementation HCDCashContext 

-(instancetype)initWithCashType:(HCDCashType)type{
    self = [super init];
    if (self) {
        [self cofigureWithCashType:type];
    }
    return self;
}

- (void)cofigureWithCashType:(HCDCashType)type {
    switch (type) {
        case HCDCashTypeNormal: {
            self.cash = [[HCDCashNormal alloc] init];
        }
        break;
        case HCDCashTypeRobate: {
            self.cash = [[HCDCashRobate alloc] initWithMoneyRebate:0.8];
        }
        break;
        case HCDCashTypeReturn: {
            self.cash = [[HCDCaseReturn alloc] initWithMoneyReturn:5];
        }
        break;
    }
}

- (CGFloat)getResult:(CGFloat)money {
    return [self.cash acceptCash:money];
}

@end
//HCDCashProtocol.h
@protocol HCDCashProtocol 

- (CGFloat)acceptCash:(CGFloat)cash;

@end
//HCDCaseReturn.h
@interface HCDCaseReturn : NSObject

-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn;

@end

//HCDCaseReturn.m
@interface HCDCaseReturn ()

@property (nonatomic, assign)CGFloat moneyReturn;

@end

@implementation HCDCaseReturn

#pragma mark - life cycle

-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn{
    self = [super init];
    if (self) {
        _moneyReturn = moneyReturn;
    }
    return self;
}

#pragma mark - HCDCashProtocol

-(CGFloat)acceptCash:(CGFloat)cash{
    return cash - self.moneyReturn;
}

@end
//HCDCashNormal.m
@implementation HCDCashNormal
 
-(CGFloat)acceptCash:(CGFloat)cash{
    return cash;
}

@end
//HCDCashRobate.h
@interface HCDCashRobate : NSObject

-(instancetype)initWithMoneyRebate:(CGFloat)moneyRebate;

@end

//HCDCashRobate.m
@interface HCDCashRobate ()

@property (nonatomic, assign) CGFloat moneyRebate;

@end

@implementation HCDCashRobate

-(instancetype)initWithMoneyRebate:(CGFloat)moneyRebate{
    self = [super init];
    if (self) {
        _moneyRebate = moneyRebate;
    }
    return self;
}

-(CGFloat)acceptCash:(CGFloat)cash{
    return self.moneyRebate * cash;
}

@end

模板方法模式

模式动机

模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一。
在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。

模式定义

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模式结构

模板方法模式包含如下角色:

  • AbstractClass: 抽象类
  • ConcreteClass: 具体子类


    读《大话设计模式》三_第12张图片
    模板方法模式类图
时序图

源码
    //使用示例
    HCDtextPaper *paperA = [[HCDtextPaperA alloc]init];
    [paperA testQuestion1];
    [paperA testQuestion2];
    
    HCDtextPaper *paperB = [[HCDtextPaperB alloc]init];
    [paperB testQuestion1];
    [paperB testQuestion2];
//HCDtextPaper.h
@interface HCDtextPaper : NSObject

- (void)testQuestion1;

- (void)testQuestion2;

/**
 子类需要重写这个方法

 @return 结果
 */
- (NSString *)answer1;

/**
 子类需要重写这个方法
 
 @return 结果
 */
- (NSString *)answer2;

@end
//HCDtextPaper.m
@implementation HCDtextPaper

-(void)testQuestion1 {
    NSLog(@"问题:杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ]:a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
    NSLog(@"答案:%@", [self answer1]);
}

-(NSString *)answer1 {
    return @"";
}

-(void)testQuestion2 {
    NSLog(@"问题:杨过、程英、陆无双铲除了情花,造成[ ]:a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
    NSLog(@"答案:%@", [self answer2]);
}

-(NSString *)answer2{
    return @"";
}

@end
//HCDtextPaperA.m
@implementation HCDtextPaperA

-(NSString *)answer1{
    return @"b";
}

-(NSString *)answer2{
    return @"c";
}

@end
//HCDtextPaperB.m
@implementation HCDtextPaperB

-(NSString *)answer1{
    return @"a";
}

-(NSString *)answer2{
    return @"d";
}

@end

职责链模式

模式动机

很多情况下,在一个软件系统中可以处理某个请求的对象不止一个。例如采购审批子系统,主任、副董事长、董事长和董事会都可以处理采购单,他们可以构成一条处理采购单的链式结构,采购单(可以看作是要处理的信息)沿着这条链进行传递,这条链就称为责任链。责任链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求,如下图所示。链上的每一个对象都是请求处理者,责任链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行相应的处理。在此过程中,客户端实际上无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,从而实现请求发送者和请求处理者解耦。

模式定义

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

模式结构

职责链模式包含如下角色:

  • Handler: 处理者抽象类
  • ConcreteAggregate: 具体处理者类
读《大话设计模式》三_第13张图片
职责链模式类图
时序图

源码
    //使用示例
    HCDCommonManager *jinli = [[HCDCommonManager alloc]initWithName:@"经理"];
    HCDMajorManager *zongjian = [[HCDMajorManager alloc]initWithName:@"总监"];
    HCDGenaralManager *zongjinli = [[HCDGenaralManager alloc]initWithName:@"总经理"];
    jinli.superior = zongjian;
    zongjian.superior = zongjinli;
    
    HCDReuquest *request = [[HCDReuquest alloc] init];
    request.requestType = @"请假";
    request.requestContent = @"小菜请假";
    request.number = 1;
    [jinli dealRequest:request];
    
    HCDReuquest *request1 = [[HCDReuquest alloc] init];
    request1.requestType = @"请假";
    request1.requestContent = @"小菜请假";
    request1.number = 4;
    [jinli dealRequest:request1];
    
    HCDReuquest *request2 = [[HCDReuquest alloc] init];
    request2.requestType = @"加薪";
    request2.requestContent = @"小菜请求加薪";
    request2.number = 500;
    [jinli dealRequest:request2];
    
    HCDReuquest *request4 = [[HCDReuquest alloc] init];
    request4.requestType = @"加薪";
    request4.requestContent = @"小菜请求加薪";
    request4.number = 1000;
    [jinli dealRequest:request4];
//HCDMnager.h
@class HCDReuquest;
@interface HCDMnager : NSObject

@property (nonatomic, copy) NSString *name;

@property (nonatomic, strong) HCDMnager *superior;

- (instancetype)initWithName:(NSString *)name;

- (void)dealRequest:(HCDReuquest *)request;

@end
//HCDCommonManager.h
@interface HCDCommonManager : HCDMnager

@end

//HCDCommonManager.m
@implementation HCDCommonManager

- (void)dealRequest:(HCDReuquest *)request{
    if ([request.requestType isEqualToString:@"请假"] && request.number <= 2) {
        NSLog(@"%@:%@ 数量%ld 被批准",self.name,request.requestType,request.number);
    }else{
        if (self.superior) {
            [self.superior dealRequest:request]; 
        }
    }
}

@end
//HCDMajorManager.h
@interface HCDMajorManager : HCDMnager

@end

//HCDMajorManager.m
@implementation HCDMajorManager

-(void)dealRequest:(HCDReuquest *)request{
    if ([request.requestType isEqualToString:@"请假"] && request.number <= 5) {
        NSLog(@"%@:%@ 数量%ld 被批准",self.name,request.requestType,request.number);
    }else{
        if (self.superior) {
            [self.superior dealRequest:request];
        }
    }
}
@end
//HCDGenaralManager.h
@interface HCDGenaralManager : HCDMnager

@end

//HCDGenaralManager.m
@implementation HCDGenaralManager

-(void)dealRequest:(HCDReuquest *)request{
    if ([request.requestType isEqualToString:@"请假"]) {
        NSLog(@"%@:%@ 数量%ld 被批准",self.name,request.requestType,request.number);
    } else if ([request.requestType isEqualToString:@"加薪"]){
        if (request.number <= 500) {
            NSLog(@"%@:%@ 数量%ld 被批准",self.name,request.requestType,request.number);
        } else {
            NSLog(@"%@:%@ 数量%ld 再说吧",self.name,request.requestType,request.number);
        }
    } else {
        
    }
}

@end
//HCDReuquest.h
@interface HCDReuquest : NSObject

/**
 请求类型
 */
@property (nonatomic, copy) NSString *requestType;

/**
 请求内容
 */
@property (nonatomic, copy) NSString *requestContent;

/**
 请求的数量
 */
@property(nonatomic, assign) NSInteger number;

@end

解释器模式

模式动机

如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题。
解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。

模式定义

给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

模式结构

解释器模式模式包含如下角色:

  • AbstractExpression: 抽象表达式
  • TerminalExpression: 终结符表达式
  • NonterminalExpression: 非终结符表达式
  • Context: 环境类
  • Client: 客户类


    读《大话设计模式》三_第14张图片
    解释器模式类图
时序图

源码

访问者模式

模式动机

访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的模式动机。

模式定义

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

模式结构

访问者模式包含如下角色:

  • Vistor: 抽象访问者。为该对象结构中的ConcreteElement的每一个类声明的一个操作。
  • ConcreteVisitor: 具体访问者。实现Visitor申明的每一个操作,每一个操作实现算法的一部分。
  • Element: 抽象元素。定义一个Accept操作,它以一个访问者为参数。
  • ConcreteElement: 具体元素 。实现Accept操作。
  • ObjectStructure: 对象结构。能够枚举它的元素,可以提供一个高层的接口来允许访问者访问它的元素。


    读《大话设计模式》三_第15张图片
    访问者模式类图
时序图

源码
    //使用示例
    HCDObjectStructure *o = [[HCDObjectStructure alloc]init];
    
    //初始化不同的element对象
    HCDConcreteElementA *eA = [HCDConcreteElementA new];
    HCDConcreteElementB *eB = [HCDConcreteElementB new];
    //加入o对象里面,存在一个数据结构o中。
    [o attach:eA];
    [o attach:eB];
    
    //初始化不同的visitor对象。
    HCDConcreteVisitor1 *v1 = [HCDConcreteVisitor1 new];
    HCDConcreteVisitor2 *v2 = [HCDConcreteVisitor2 new];
    //eA,eB(男人女人)接收到访问者v1(喜)的不同反应。
    [o accept:v1];
    NSLog(@"================================");
    //eA,eB(男人女人)接收到访问者v2(怒)的不同反应。
    [o accept:v2];
//HCDObjectStructure.h
@class HCDElements;
@class HCDVisitors;

@interface HCDObjectStructure : NSObject

-(void)attach:(HCDElements *)element;

-(void)detach:(HCDElements *)element;

-(void)accept:(HCDVisitors *)visitor;

@end
//HCDObjectStructure.m
@interface HCDObjectStructure ()

@property (nonatomic, strong) NSMutableArray *elements;

@end

@implementation HCDObjectStructure

-(instancetype)init{
    self = [super init];
    if (self) {
        _elements = [[NSMutableArray alloc]init];
    }
    return self;
}

-(void)attach:(HCDElements *)element{
    [self.elements addObject:element];
}

-(void)detach:(HCDElements *)element{
    [self.elements removeObject:element];
}

-(void)accept:(HCDVisitors *)visitor{
    for (HCDElements *e in self.elements) {
        [e accept:visitor];
    }
}

@end
//HCDVisitors.h
@interface HCDVisitors : NSObject

-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA;

-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB;

@end

//HCDConcreteVisitor1.h
@interface HCDConcreteVisitor1 : HCDVisitors

@end

//HCDConcreteVisitor1.m
@implementation HCDConcreteVisitor1

-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA{
    NSLog(@"男人接收到喜这个visitor============我要飞");
}

-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB{
    NSLog(@"女人接收到喜这个visitor============我要跳");
}

@end

//HCDConcreteVisitor2.h
@interface HCDConcreteVisitor2 : HCDVisitors

@end

//HCDConcreteVisitor2.m
@implementation HCDConcreteVisitor2

-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA{
    NSLog(@"男人接收到怒这个visitor============我要叫");
}

-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB{
    NSLog(@"女人接收到怒这个visitor============我要苦");
}

@end
//HCDElements.h
@class HCDVisitors;
@interface HCDElements : NSObject

-(void)accept:(HCDVisitors *)visitor;

@end
//HCDConcreteElementA.m
@implementation HCDConcreteElementA

-(void)operationA{
    return;
}

-(void)accept:(HCDVisitors *)visitor{
    [visitor visitConcreteElementA:self];
}

@end
//HCDConcreteElementB.m
@implementation HCDConcreteElementB

-(void)operationB{
    return;
}

-(void)accept:(HCDVisitors *)visitor{
    [visitor visitConcreteElementB:self];
}

@end

小结

在实际的项目开发过程中,使用某些特定的设计模式能够很好的解决问题。同时,在维护他人编写的代码时,如果对设计模式特别熟悉,遇到时也比较容易定位问题。
源码和demo请点这里
参考的文章链接如下
Graphic Design Patterns

你可能感兴趣的:(读《大话设计模式》三)