讀《大話設(shè)計(jì)模式》三

行為型模式

迭代器模式

模式動(dòng)機(jī)

針對(duì)不同的需要泊脐,可能還要以不同的方式遍歷整個(gè)聚合對(duì)象备蚓,但是我們并不希望在聚合對(duì)象的抽象層接口中充斥著各種不同遍歷的操作课蔬。
怎樣遍歷一個(gè)聚合對(duì)象,又不需要了解聚合對(duì)象的內(nèi)部結(jié)構(gòu)郊尝,還能夠提供多種不同的遍歷方式二跋,這就是迭代器模式的模式動(dòng)機(jī)。

模式定義

提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中的各個(gè)元素流昏,而又不暴露該對(duì)象的內(nèi)部表示扎即。

模式結(jié)構(gòu)

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

  • Aggregate: 聚集抽象類
  • ConcreteAggregate: 具體聚集類
  • Iterator: 迭代抽象類
  • ConcreteIterator: 具體迭代器類
迭代器模式類圖
時(shí)序圖

源碼

行為型

命令模式

模式動(dòng)機(jī)

在軟件設(shè)計(jì)中吞获,我們經(jīng)常需要向某些對(duì)象發(fā)送請(qǐng)求,但是并不知道請(qǐng)求的接收者是誰(shuí)谚鄙,也不知道被請(qǐng)求的操作是哪個(gè)各拷,我們只需在程序運(yùn)行時(shí)指定具體的請(qǐng)求接收者即可,此時(shí)闷营,可以使用命令模式來(lái)進(jìn)行設(shè)計(jì)烤黍,使得請(qǐng)求發(fā)送者與請(qǐng)求接收者消除彼此之間的耦合,讓對(duì)象之間的調(diào)用關(guān)系更加靈活傻盟。

命令模式可以對(duì)發(fā)送者和接收者完全解耦速蕊,發(fā)送者與接收者之間沒(méi)有直接引用關(guān)系,發(fā)送請(qǐng)求的對(duì)象只需要知道如何發(fā)送請(qǐng)求莫杈,而不必知道如何完成請(qǐng)求互例。這就是命令模式的模式動(dòng)機(jī)。

模式定義

命令模式(Command Pattern):將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象筝闹,從而使我們可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志腥光,以及支持可撤銷的操作关顷。命令模式是一種對(duì)象行為型模式,其別名為動(dòng)作(Action)模式或事務(wù)(Transaction)模式武福。

模式結(jié)構(gòu)

命令模式包含如下角色:

  • Command: 抽象命令類
  • ConcreteCommand: 具體命令類
  • Invoker: 調(diào)用者
  • Receiver: 接收者
  • Client:客戶類


    命令模式類圖
時(shí)序圖
命令模式時(shí)序圖
源碼
//使用示例
    //waiter用于接收各種類型的order议双。waiter是請(qǐng)求接收者。
    //接收不同customer產(chǎn)生的不同order捉片,并且都存入waiter這個(gè)接受者中,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發(fā)送order,背后有一個(gè)HCDWorker這個(gè)單列作為行為實(shí)現(xiàn)者來(lái)處理具體的order伍纫。命令接收完畢宗雇,開(kāi)始發(fā)送命令。
    [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];
}
/*
 命令接收完畢莹规,開(kāi)始執(zhí)行命令
 */
-(void)notifyOrder{
    NSLog(@"====開(kāi)始執(zhí)行Order===");
    for (HCDOrder *order in self.orderList) {
        [order executeOrder];
    }
}
@end
//HCDOrder.h
@interface HCDOrder : NSObject

@property(nonatomic,copy)NSString *orderString;

-(instancetype)initWithOrderString:(NSString *)orderString;
//執(zhí)行命令
-(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

中介者模式

模式動(dòng)機(jī)
  • 在用戶與用戶直接聊天的設(shè)計(jì)方案中赔蒲,用戶對(duì)象之間存在很強(qiáng)的關(guān)聯(lián)性,將導(dǎo)致系統(tǒng)出現(xiàn)如下問(wèn)題:
  • 系統(tǒng)結(jié)構(gòu)復(fù)雜:對(duì)象之間存在大量的相互關(guān)聯(lián)和調(diào)用良漱,若有一個(gè)對(duì)象發(fā)生變化舞虱,則需要跟蹤和該對(duì)象關(guān)聯(lián)的其他所有對(duì)象,并進(jìn)行適當(dāng)處理母市。
  • 對(duì)象可重用性差:由于一個(gè)對(duì)象和其他對(duì)象具有很強(qiáng)的關(guān)聯(lián)矾兜,若沒(méi)有其他對(duì)象的支持,一個(gè)對(duì)象很難被另一個(gè)系統(tǒng)或模塊重用患久,這些對(duì)象表現(xiàn)出來(lái)更像一個(gè)不可分割的整體椅寺,職責(zé)較為混亂浑槽。
  • 系統(tǒng)擴(kuò)展性低:增加一個(gè)新的對(duì)象需要在原有相關(guān)對(duì)象上增加引用,增加新的引用關(guān)系也需要調(diào)整原有對(duì)象配并,系統(tǒng)耦合度很高括荡,對(duì)象操作很不靈活,擴(kuò)展性差溉旋。
  • 在面向?qū)ο蟮能浖O(shè)計(jì)與開(kāi)發(fā)過(guò)程中畸冲,根據(jù)“單一職責(zé)原則”,我們應(yīng)該盡量將對(duì)象細(xì)化观腊,使其只負(fù)責(zé)或呈現(xiàn)單一的職責(zé)邑闲。
  • 對(duì)于一個(gè)模塊,可能由很多對(duì)象構(gòu)成梧油,而且這些對(duì)象之間可能存在相互的引用苫耸,為了減少對(duì)象兩兩之間復(fù)雜的引用關(guān)系,使之成為一個(gè)松耦合的系統(tǒng)儡陨,我們需要使用中介者模式褪子,這就是中介者模式的模式動(dòng)機(jī)。
模式定義

中介者模式(Mediator Pattern)定義:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互骗村,中介者使各對(duì)象不需要顯式地相互引用嫌褪,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互胚股。它是一種對(duì)象行為型模式笼痛。

模式結(jié)構(gòu)

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

  • Mediator: 抽象中介者
  • ConcreteMediator: 具體中介者
  • Colleague: 抽象同事類
  • ConcreteColleague: 具體同事類


    中介者模式類圖
時(shí)序圖
中介者模式時(shí)序圖
源碼
    //使用示例
    ConcreteMediator *mediator = [[ConcreteMediator alloc] init];
    
    //初始化并且讓兩個(gè)同事有相同的中介者對(duì)象
    ConcreteColleague1 *c1 = [[ConcreteColleague1 alloc] initWithMediator:mediator];
    ConcreteColleague2 *c2 = [[ConcreteColleague2 alloc] initWithMediator:mediator];
    
    //給中介者對(duì)象綁定兩個(gè)要交互的同事對(duì)象
    mediator.colleague1 = c1;
    mediator.colleague2 = c2;
    
    [c1 send:@"吃過(guò)飯了嗎?"];
    [c2 send:@"沒(méi)有呢琅拌,你打算請(qǐng)客缨伊?"];
//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發(fā)送了信息");
    [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發(fā)送了信息");
    [self.mediator send:message colleague:self];
}

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

@end

觀察者模式

模式動(dòng)機(jī)

建立一種對(duì)象與對(duì)象之間的依賴關(guān)系,一個(gè)對(duì)象發(fā)生改變時(shí)將自動(dòng)通知其他對(duì)象进宝,其他對(duì)象將相應(yīng)做出反應(yīng)刻坊。在此,發(fā)生改變的對(duì)象稱為觀察目標(biāo)即彪,而被通知的對(duì)象稱為觀察者紧唱,一個(gè)觀察目標(biāo)可以對(duì)應(yīng)多個(gè)觀察者,而且這些觀察者之間沒(méi)有相互聯(lián)系隶校,可以根據(jù)需要增加和刪除觀察者漏益,使得系統(tǒng)更易于擴(kuò)展,這就是觀察者模式的模式動(dòng)機(jī)深胳。

模式定義

觀察者模式(Observer Pattern):定義對(duì)象間的一種一對(duì)多依賴關(guān)系绰疤,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新舞终。觀察者模式是一種對(duì)象行為型模式轻庆。

模式結(jié)構(gòu)

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

  • Subject: 目標(biāo)
  • ConcreteSubject: 具體目標(biāo)
  • Observer: 觀察者
  • ConcreteObserver: 具體觀察者


    觀察者模式類圖
時(shí)序圖
觀察者模式時(shí)序圖
源碼
//使用示例
- (void)viewDidLoad {
    [super viewDidLoad];
    
    HCDServiceCenter *serviceCenter = [[HCDServiceCenter alloc] init];
    
    [serviceCenter addDelegate:self.nbaobserver];
    [serviceCenter addDelegate:self.stockobserver];
    [serviceCenter addDelegate:self.gameObserver];
    
    NSLog(@"秘書(shū)通知:老板回來(lái)了癣猾,大家趕緊撤"); 
    [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 <NSObject>

@optional
- (void)update;

@end

//HCDStockObserver.h
@interface HCDStockObserver : NSObject<HCDObserver>

@end

//HCDNBAObserver.h
@interface HCDNBAObserver : NSObject<HCDObserver>

@end

//HCDGameObserver.h
@interface HCDGameObserver : NSObject<HCDObserver>

@end

狀態(tài)模式

模式動(dòng)機(jī)

在很多情況下,一個(gè)對(duì)象的行為取決于一個(gè)或多個(gè)動(dòng)態(tài)變化的屬性余爆,這樣的屬性叫做狀態(tài)纷宇,這樣的對(duì)象叫做有狀態(tài)的(stateful)對(duì)象,這樣的對(duì)象狀態(tài)是從事先定義好的一系列值中取出的蛾方。當(dāng)一個(gè)這樣的對(duì)象與外部事件產(chǎn)生互動(dòng)時(shí)像捶,其內(nèi)部狀態(tài)就會(huì)改變,從而使得系統(tǒng)的行為也隨之發(fā)生變化桩砰。

狀態(tài)模式主要解決的是當(dāng)控制一個(gè)對(duì)象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過(guò)于負(fù)責(zé)時(shí)的情況拓春。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類當(dāng)中,可以把復(fù)雜的判斷邏輯簡(jiǎn)化亚隅。

模式定義

允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為硼莽,對(duì)象看起來(lái)似乎修改了它的類。狀態(tài)模式是一種對(duì)象行為型模式煮纵。

模式結(jié)構(gòu)

狀態(tài)模式包含如下角色:

  • Context: 環(huán)境類
  • State: 抽象狀態(tài)類
  • ConcreteState: 具體狀態(tài)類


    狀態(tài)模式類圖
時(shí)序圖
狀態(tài)模式時(shí)序圖
源碼
    //使用示例
    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 <NSObject>

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

@end
//HCDState.h
@interface HCDState : NSObject<HCDProtocol>

@end
//HCDForenoonState.m
@implementation HCDForenoonState

-(void)writeProgram:(HCDWork *)work{
    if (work.hour < 12) {
         NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)懂鸵,上午工作,精神百倍", 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(@"當(dāng)前時(shí)間:{%.f}點(diǎn)行疏,餓了矾瑰,午飯;犯困隘擎,午休", 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(@"當(dāng)前時(shí)間:{%.f}點(diǎn),下午狀態(tài)還不錯(cuò)凉夯,繼續(xù)努力", 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(@"當(dāng)前時(shí)間:{%.f}點(diǎn)货葬,加班哦,疲累之極", work.hour);
        } else {
            HCDSleepState *sleepState = [[HCDSleepState alloc] init];
            [work changeState:sleepState]; 
            [work writeProgram];
        }
    }

}

@end
//HCDSleepState.m
@implementation HCDSleepState

- (void)writeProgram:(HCDWork *)work {
    NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)劲够,不行了震桶,睡著了", work.hour);
}
@end
//HCDRestState.m
@implementation HCDRestState

- (void)writeProgram:(HCDWork *)work {
    NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn),下班回家了", work.hour);
}
@end

策略模式

模式動(dòng)機(jī)
  • 完成一項(xiàng)任務(wù)征绎,往往可以有多種不同的方式蹲姐,每一種方式稱為一個(gè)策略,我們可以根據(jù)環(huán)境或者條件的不同選擇不同的策略來(lái)完成該項(xiàng)任務(wù)人柿。
  • 在軟件開(kāi)發(fā)中也常常遇到類似的情況柴墩,實(shí)現(xiàn)某一個(gè)功能有多個(gè)途徑,此時(shí)可以使用一種設(shè)計(jì)模式來(lái)使得系統(tǒng)可以靈活地選擇解決途徑凫岖,也能夠方便地增加新的解決途徑江咳。
  • 為了解決這些問(wèn)題,可以定義一些獨(dú)立的類來(lái)封裝不同的算法哥放,每一個(gè)類封裝一個(gè)具體的算法歼指,在這里爹土,每一個(gè)封裝算法的類我們都可以稱之為策略(Strategy),為了保證這些策略的一致性踩身,一般會(huì)用一個(gè)抽象的策略類來(lái)做算法的定義胀茵,而具體每種算法則對(duì)應(yīng)于一個(gè)具體策略類。
模式定義

定義了算法家族挟阻,分別封裝起來(lái)琼娘,讓它們之間可以互相替換,此模式讓算法的變化赁濒,不會(huì)影響到使用算法的客戶轨奄。

模式結(jié)構(gòu)

策略模式包含如下角色:

  • Context: 環(huán)境類
  • Strategy: 抽象策略類
  • ConcreteStrategy: 具體策略類
策略模式類圖
時(shí)序圖
策略模式時(shí)序圖
源碼
    //使用示例
    HCDCashContext *context = [[HCDCashContext alloc] initWithCashType:HCDCashTypeNormal];
    NSLog(@"結(jié)果是%f",[context getResult:100]);

    HCDCashContext *contextReturn = [[HCDCashContext alloc] initWithCashType:HCDCashTypeReturn];
    NSLog(@"結(jié)果是%f",[contextReturn getResult:100]);
    
    HCDCashContext *contextRobate = [[HCDCashContext alloc] initWithCashType:HCDCashTypeRobate];
    NSLog(@"結(jié)果是%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<HCDCashProtocol> 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 <NSObject>

- (CGFloat)acceptCash:(CGFloat)cash;

@end
//HCDCaseReturn.h
@interface HCDCaseReturn : NSObject<HCDCashProtocol>

-(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<HCDCashProtocol>

-(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

模板方法模式

模式動(dòng)機(jī)

模板方法模式是基于繼承的代碼復(fù)用基本技術(shù),模板方法模式的結(jié)構(gòu)和用法也是面向?qū)ο笤O(shè)計(jì)的核心之一拒炎。
在模板方法模式中挪拟,可以將相同的代碼放在父類中,而將不同的方法實(shí)現(xiàn)放在不同的子類中。

模式定義

定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中锈玉。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟惹苗。

模式結(jié)構(gòu)

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

  • AbstractClass: 抽象類
  • ConcreteClass: 具體子類


    模板方法模式類圖
時(shí)序圖

源碼
    //使用示例
    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;

/**
 子類需要重寫(xiě)這個(gè)方法

 @return 結(jié)果
 */
- (NSString *)answer1;

/**
 子類需要重寫(xiě)這個(gè)方法
 
 @return 結(jié)果
 */
- (NSString *)answer2;

@end
//HCDtextPaper.m
@implementation HCDtextPaper

-(void)testQuestion1 {
    NSLog(@"問(wèn)題:楊過(guò)得到,后來(lái)給了郭靖邪驮,煉成倚天劍、屠龍刀的玄鐵可能是[ ]:a.球磨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳素纖維");
    NSLog(@"答案:%@", [self answer1]);
}

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

-(void)testQuestion2 {
    NSLog(@"問(wèn)題:楊過(guò)、程英石景、陸無(wú)雙鏟除了情花,造成[ ]:a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個(gè)生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化");
    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

職責(zé)鏈模式

模式動(dòng)機(jī)

很多情況下拙吉,在一個(gè)軟件系統(tǒng)中可以處理某個(gè)請(qǐng)求的對(duì)象不止一個(gè)潮孽。例如采購(gòu)審批子系統(tǒng),主任筷黔、副董事長(zhǎng)往史、董事長(zhǎng)和董事會(huì)都可以處理采購(gòu)單,他們可以構(gòu)成一條處理采購(gòu)單的鏈?zhǔn)浇Y(jié)構(gòu)佛舱,采購(gòu)單(可以看作是要處理的信息)沿著這條鏈進(jìn)行傳遞椎例,這條鏈就稱為責(zé)任鏈。責(zé)任鏈可以是一條直線请祖、一個(gè)環(huán)或者一個(gè)樹(shù)形結(jié)構(gòu)订歪,最常見(jiàn)的職責(zé)鏈?zhǔn)侵本€型,即沿著一條單向的鏈來(lái)傳遞請(qǐng)求损拢,如下圖所示陌粹。鏈上的每一個(gè)對(duì)象都是請(qǐng)求處理者,責(zé)任鏈模式可以將請(qǐng)求的處理者組織成一條鏈,并讓請(qǐng)求沿著鏈傳遞掏秩,由鏈上的處理者對(duì)請(qǐng)求進(jìn)行相應(yīng)的處理或舞。在此過(guò)程中,客戶端實(shí)際上無(wú)須關(guān)心請(qǐng)求的處理細(xì)節(jié)以及請(qǐng)求的傳遞蒙幻,只需將請(qǐng)求發(fā)送到鏈上即可映凳,從而實(shí)現(xiàn)請(qǐng)求發(fā)送者和請(qǐng)求處理者解耦。

模式定義

使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求邮破,從而避免請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系诈豌。將這個(gè)對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求抒和,直到有一個(gè)對(duì)象處理它為止矫渔。

模式結(jié)構(gòu)

職責(zé)鏈模式包含如下角色:

  • Handler: 處理者抽象類
  • ConcreteAggregate: 具體處理者類
職責(zé)鏈模式類圖
時(shí)序圖

源碼
    //使用示例
    HCDCommonManager *jinli = [[HCDCommonManager alloc]initWithName:@"經(jīng)理"];
    HCDMajorManager *zongjian = [[HCDMajorManager alloc]initWithName:@"總監(jiān)"];
    HCDGenaralManager *zongjinli = [[HCDGenaralManager alloc]initWithName:@"總經(jīng)理"];
    jinli.superior = zongjian;
    zongjian.superior = zongjinli;
    
    HCDReuquest *request = [[HCDReuquest alloc] init];
    request.requestType = @"請(qǐng)假";
    request.requestContent = @"小菜請(qǐng)假";
    request.number = 1;
    [jinli dealRequest:request];
    
    HCDReuquest *request1 = [[HCDReuquest alloc] init];
    request1.requestType = @"請(qǐng)假";
    request1.requestContent = @"小菜請(qǐng)假";
    request1.number = 4;
    [jinli dealRequest:request1];
    
    HCDReuquest *request2 = [[HCDReuquest alloc] init];
    request2.requestType = @"加薪";
    request2.requestContent = @"小菜請(qǐng)求加薪";
    request2.number = 500;
    [jinli dealRequest:request2];
    
    HCDReuquest *request4 = [[HCDReuquest alloc] init];
    request4.requestType = @"加薪";
    request4.requestContent = @"小菜請(qǐng)求加薪";
    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:@"請(qǐng)假"] && request.number <= 2) {
        NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",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:@"請(qǐng)假"] && request.number <= 5) {
        NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",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:@"請(qǐng)假"]) {
        NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
    } else if ([request.requestType isEqualToString:@"加薪"]){
        if (request.number <= 500) {
            NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
        } else {
            NSLog(@"%@:%@ 數(shù)量%ld 再說(shuō)吧",self.name,request.requestType,request.number);
        }
    } else {
        
    }
}

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

/**
 請(qǐng)求類型
 */
@property (nonatomic, copy) NSString *requestType;

/**
 請(qǐng)求內(nèi)容
 */
@property (nonatomic, copy) NSString *requestContent;

/**
 請(qǐng)求的數(shù)量
 */
@property(nonatomic, assign) NSInteger number;

@end

解釋器模式

模式動(dòng)機(jī)

如果在系統(tǒng)中某一特定類型的問(wèn)題發(fā)生的頻率很高,此時(shí)可以考慮將這些問(wèn)題的實(shí)例表述為一個(gè)語(yǔ)言中的句子摧莽,因此可以構(gòu)建一個(gè)解釋器庙洼,該解釋器通過(guò)解釋這些句子來(lái)解決這些問(wèn)題。
解釋器模式描述了如何構(gòu)成一個(gè)簡(jiǎn)單的語(yǔ)言解釋器镊辕,主要應(yīng)用在使用面向?qū)ο笳Z(yǔ)言開(kāi)發(fā)的編譯器中油够。

模式定義

給定一種語(yǔ)言,定義它的文法的一種表示征懈,并定義一個(gè)解釋器石咬,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。

模式結(jié)構(gòu)

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

  • AbstractExpression: 抽象表達(dá)式
  • TerminalExpression: 終結(jié)符表達(dá)式
  • NonterminalExpression: 非終結(jié)符表達(dá)式
  • Context: 環(huán)境類
  • Client: 客戶類


    解釋器模式類圖
時(shí)序圖

源碼

訪問(wèn)者模式

模式動(dòng)機(jī)

訪問(wèn)者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作卖哎,一旦這些操作需要修改的話鬼悠,接受這個(gè)操作的數(shù)據(jù)結(jié)構(gòu)可以保持不變。為不同類型的元素提供多種訪問(wèn)操作方式亏娜,且可以在不修改原有系統(tǒng)的情況下增加新的操作方式厦章,這就是訪問(wèn)者模式的模式動(dòng)機(jī)。

模式定義

表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作照藻。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

模式結(jié)構(gòu)

訪問(wèn)者模式包含如下角色:

  • Vistor: 抽象訪問(wèn)者汗侵。為該對(duì)象結(jié)構(gòu)中的ConcreteElement的每一個(gè)類聲明的一個(gè)操作幸缕。
  • ConcreteVisitor: 具體訪問(wèn)者。實(shí)現(xiàn)Visitor申明的每一個(gè)操作晰韵,每一個(gè)操作實(shí)現(xiàn)算法的一部分发乔。
  • Element: 抽象元素。定義一個(gè)Accept操作雪猪,它以一個(gè)訪問(wèn)者為參數(shù)栏尚。
  • ConcreteElement: 具體元素 。實(shí)現(xiàn)Accept操作只恨。
  • ObjectStructure: 對(duì)象結(jié)構(gòu)译仗。能夠枚舉它的元素抬虽,可以提供一個(gè)高層的接口來(lái)允許訪問(wèn)者訪問(wèn)它的元素。


    訪問(wèn)者模式類圖
時(shí)序圖

源碼
    //使用示例
    HCDObjectStructure *o = [[HCDObjectStructure alloc]init];
    
    //初始化不同的element對(duì)象
    HCDConcreteElementA *eA = [HCDConcreteElementA new];
    HCDConcreteElementB *eB = [HCDConcreteElementB new];
    //加入o對(duì)象里面纵菌,存在一個(gè)數(shù)據(jù)結(jié)構(gòu)o中阐污。
    [o attach:eA];
    [o attach:eB];
    
    //初始化不同的visitor對(duì)象。
    HCDConcreteVisitor1 *v1 = [HCDConcreteVisitor1 new];
    HCDConcreteVisitor2 *v2 = [HCDConcreteVisitor2 new];
    //eA,eB(男人女人)接收到訪問(wèn)者v1(喜)的不同反應(yīng)咱圆。
    [o accept:v1];
    NSLog(@"================================");
    //eA,eB(男人女人)接收到訪問(wèn)者v2(怒)的不同反應(yīng)笛辟。
    [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(@"男人接收到喜這個(gè)visitor============我要飛");
}

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

@end

//HCDConcreteVisitor2.h
@interface HCDConcreteVisitor2 : HCDVisitors

@end

//HCDConcreteVisitor2.m
@implementation HCDConcreteVisitor2

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

-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB{
    NSLog(@"女人接收到怒這個(gè)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

小結(jié)

在實(shí)際的項(xiàng)目開(kāi)發(fā)過(guò)程中,使用某些特定的設(shè)計(jì)模式能夠很好的解決問(wèn)題序苏。同時(shí)手幢,在維護(hù)他人編寫(xiě)的代碼時(shí),如果對(duì)設(shè)計(jì)模式特別熟悉忱详,遇到時(shí)也比較容易定位問(wèn)題围来。
源碼和demo請(qǐng)點(diǎn)這里
參考的文章鏈接如下
Graphic Design Patterns

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市踱阿,隨后出現(xiàn)的幾起案子管钳,更是在濱河造成了極大的恐慌,老刑警劉巖软舌,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件才漆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡佛点,警方通過(guò)查閱死者的電腦和手機(jī)醇滥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)超营,“玉大人鸳玩,你說(shuō)我怎么就攤上這事⊙荼眨” “怎么了不跟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)米碰。 經(jīng)常有香客問(wèn)我窝革,道長(zhǎng),這世上最難降的妖魔是什么吕座? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任虐译,我火速辦了婚禮,結(jié)果婚禮上吴趴,老公的妹妹穿的比我還像新娘漆诽。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布厢拭。 她就那樣靜靜地躺著兰英,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚪腐。 梳的紋絲不亂的頭發(fā)上箭昵,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音回季,去河邊找鬼家制。 笑死,一個(gè)胖子當(dāng)著我的面吹牛泡一,可吹牛的內(nèi)容都是我干的颤殴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鼻忠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼涵但!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起帖蔓,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤矮瘟,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后塑娇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澈侠,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年埋酬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哨啃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡写妥,死狀恐怖拳球,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情珍特,我是刑警寧澤祝峻,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站扎筒,受9級(jí)特大地震影響呼猪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砸琅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轴踱。 院中可真熱鬧症脂,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至棕所,卻和暖如春闸盔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背琳省。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工迎吵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人针贬。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓击费,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親桦他。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔫巩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚、低耦合和單一職能的“沖突”實(shí)際上快压,這兩者...
    彥幀閱讀 3,752評(píng)論 0 14
  • 設(shè)計(jì)模式匯總 一圆仔、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,948評(píng)論 1 15
  • 設(shè)計(jì)模式基本原則 開(kāi)放-封閉原則(OCP)蔫劣,是說(shuō)軟件實(shí)體(類坪郭、模塊、函數(shù)等等)應(yīng)該可以拓展拦宣,但是不可修改截粗。開(kāi)-閉原...
    西山薄涼閱讀 3,806評(píng)論 3 14
  • 前言 對(duì)設(shè)計(jì)模式的理解,不夠透徹鸵隧,有時(shí)去找資料绸罗,總是零零散散,不成系統(tǒng)豆瘫,故將《大話設(shè)計(jì)模式》中的干貨整理下,方便需...
    LeverTsui閱讀 603評(píng)論 0 1
  • 去年看了《敦刻爾克》。說(shuō)實(shí)話大半時(shí)候豆瓣的評(píng)分都是蠻靠譜的。藝術(shù)來(lái)源于生活砸喻,敦刻爾克作為二戰(zhàn)的一個(gè)片斷,是值得記憶...
    彼岸流星閱讀 249評(píng)論 0 2