大話設計模式

設計模式這個東西,感受就跟太極同樣,不是固定招式,須要學會而後忘記而後融會貫通。我看《大話設計模式》一書,前先後後大概看了一個月,看完一個本身用OC實現一個,到今天終於看完了。代碼我已經上傳到了GitHub,你們有興趣的話能夠下載看一眼,下面是代碼目錄java

入口是ViewController,層級自我感受良好。ios

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//    [self factoryPattern];//工廠模式
//    [self strategyPattern];//策略模式 + 工廠模式
//    [self DecorativePattern];//裝飾模式
//    [self proxyPattern];//代理模式
//    [self factoryMethodPattern];//工廠方法模式
//    [self prototypePattern];//原型模式
//    [self templateMethodPattern];//模板方法模式
//    [self appearancePattern];//外觀模式
//    [self builderPattern];//建造者模式
//    [self oberverPattern];//觀察者模式
//    [self abstraceFactoryPattern];//抽象工廠模式
//    [self statePattern];//狀態模式
//    [self adapterPattern];//適配器模式
//    [self mementoPattern];//備忘錄模式
//    [self combinatorialPattern];//組合模式
//    [self iteratorPattern];//迭代器模式
//    [self sigletonPattern];//單例模式
//    [self bridgePattern];//橋接模式
//    [self commandPattern];//命令模式
//    [self chainOfResponsibilityPattern];//職責鏈模式
//    [self mediatorPattern];//中介者模式
//    [self flyweightPattern];//享元模式
//    [self interpreterPattern];//解釋器模式
//    [self visitorPattern];//訪問者模式
}
複製代碼

這裏把各個模式的簡單介紹貼一下,具體內容請到GitHub自行下載。git

#pragma mark - 訪問者模式
/**
 *  訪問者模式:表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下
 *  定義做用於這些元素的新操做。
 *
 *  書中的例子是輸出了一段話,男人成功XXX,女人成功XXX,男人失敗XXX,女人失敗XXX,男人戀愛XXX,
 *  女人戀愛XXX。 這個例子能用訪問者模式的前提是人 只有男人跟女人兩個類,用了訪問者模式以後,若是
 *  要加一個狀態男人吃飯XXX,女人吃飯XXX,那麼只須要增長一個吃飯的狀態就能夠了。不然的話須要在男人
 *  類裏增長一個吃飯狀態,在女人類裏增長一個吃飯狀態。
 *
 *  此類比較複雜,我在實現的時候也是參照了UML圖。
 */
- (void)visitorPattern{
    TFQObjectManager *manager = [[TFQObjectManager alloc] init];
    TFQMan *man = [[TFQMan alloc] initWithName:@"男人"];
    TFQWoman *woman = [[TFQWoman alloc] initWithName:@"女人"];
    [manager addPerson:man];
    [manager addPerson:woman];
    
    TFQPersonStateSuccess *success = [[TFQPersonStateSuccess alloc] init];
    success.name = @"成功";
    TFQPersonStateFail *fail = [[TFQPersonStateFail alloc] init];
    fail.name = @"失敗";
 
    [manager display:success];
    [manager display:fail];
}

#pragma mark - 解釋器模式
/**
 *  解釋器模式:給定一個語言,定義它的文法中的一中表示,並定義一個解釋器,這個解釋器使用該
 *  表示來解釋語言中的句子。
 *
 *  書中舉的例子晦澀難懂,我對曲譜這種東西有一種先天的抗拒,那就只好本身寫一個通俗易懂的例子
 *  來解釋一下這個解釋器模式。可是我從心底裏感受這個解釋器模式就是對一種或者一系列行文封裝成
 *  一個方法,而後調用這個方法來達到目的。相似於工做流同樣的東西經過一個很是簡便的操做來實現
 *  一些常常發生的操做。 就像曲譜同樣,你經過輸入 「1234」 就能夠播放dao ruai mi fa,這就是解釋器
 *  模式
 */
- (void)interpreterPattern{
    TFQMusicManager *musicManager = [[TFQMusicManager alloc] init];
    NSString *str = @"12343215";
    [musicManager accept:str];
}

#pragma mark - 享元模式
/**
 *  享元模式:運用共享技術有效地支持大量細粒度的對象。
 *
 *  書中舉的例子是小菜作網站,作完以後又須要作一個大致相似的網站,直接複製過去也能實現
 *  功能,可是浪費內存浪費時間,這時候就用到了共享模式,把相同的對象用同一個key,存放到字典中。
 *  這樣基本上不用建立新對象就能夠實現功能。代碼中解釋的很詳細了。能夠研讀代碼。
 */
- (void)flyweightPattern{
    TFQWebFactory *webFactory = [[TFQWebFactory alloc] init];
    TFQWebSite *site1 = [webFactory getWebSiteWithType:@"公司簡介"];
    site1.user = [[TFQWebUser alloc] initWithName:@"張三"];
    TFQWebSite *site2 = [webFactory getWebSiteWithType:@"博客"];
    site2.user = [[TFQWebUser alloc] initWithName:@"張si"];
    TFQWebSite *site3 = [webFactory getWebSiteWithType:@"公司簡介"];
    site3.user = [[TFQWebUser alloc] initWithName:@"張五"];
    TFQWebSite *site4 = [webFactory getWebSiteWithType:@"公司簡介"];
    site4.user = [[TFQWebUser alloc] initWithName:@"張六"];
    
    [webFactory outputWebsites];
}

#pragma mark - 中介者模式
/**
 *  中介者模式:用一箇中介者對象來封裝一系列的對象交互。中介者使各對象不須要顯式地相互
 *  引用,從而使其耦合鬆散,並且能夠獨立地改變他們之間的交互。
 *
 *  書中的例子是舉得聯合國的例子,各國之間交流都要經過聯合國。讓聯合國持有各個國家的屬性,
 *  國家的任何交流都要經過聯合國轉達。
 */
- (void)mediatorPattern{
    TFQUnitedNations *UN = [[TFQUnitedNations alloc] init];
    TFQUSA *USA = [[TFQUSA alloc] initWithMediator:UN];
    USA.name = @"美國";
    TFQIraq *Iraq = [[TFQIraq alloc] initWithMediator:UN];
    Iraq.name = @"伊拉克";
    UN.USA = USA;
    UN.Iraq = Iraq;
 
    [USA sendMessage:@"我要打你"];
    [Iraq sendMessage:@"我不要你打"];
}

#pragma mark - 職責鏈模式
/**
 *  職責鏈模式:使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。
 *  將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它位置。
 *
 *  書中舉得例子是小菜請求加薪,而後須要經理、總監、總經理依次審批。開始的代碼是if判斷,
 *  雖然也能完成任務,可是略顯笨拙,改用職責鏈模式以後就洋氣了許多。
 *  我的感受職責鏈模式跟狀態模式是同樣的,都是分狀況,可是區別是啥呢,職責鏈的層級比較明顯,
 *  職責是一步一步變大的,側重性比較強。
 */
- (void)chainOfResponsibilityPattern{
    TFQRequest *request = [[TFQRequest alloc] init];
    request.requestName = @"張三";
//    request.requestType = @"加薪";
//    request.requestCount = 20000;
        request.requestType = @"請假";
        request.requestCount = 100;
    TFQLeader1 *leader1 = [[TFQLeader1 alloc] initWithName:@"小領導"];
    TFQLeader2 *leader2 = [[TFQLeader2 alloc] initWithName:@"中領導"];
    TFQLeader3 *leader3 = [[TFQLeader3 alloc] initWithName:@"大領導"];
    leader1.superior = leader2;
    leader2.superior = leader3;
    
    [leader1 handelRequest:request];
}

#pragma mark - 命令模式
/**
 *  命令模式:將一個請求封裝爲一個對象,從而使你可用不一樣的請求對客戶進行參數化;
 *  對請求排隊或記錄請求日誌,以及支持可撤銷的操做。
 *
 *  書中的例子講的是小菜大鳥去吃烤串,而後用代碼實現點烤串的操做,這時候就須要用低耦合的方式實現。
 */
- (void)commandPattern{
    TFQWaiter *waiter = [[TFQWaiter alloc] init];
    TFQCook *cook = [[TFQCook alloc] init];
    TFQChickenWing *wing = [[TFQChickenWing alloc] initWithCooke:cook];
    TFQSkewer *skewer = [[TFQSkewer alloc] initWithCooke:cook];
    
    [waiter receiveCommand:wing];
    [waiter receiveCommand:skewer];
    [waiter receiveCommand:wing];
    [waiter notifyCook];
}

#pragma mark - 橋接模式
/**
 *  橋接模式:講抽象部分與他的實現部分分離,使他們均可以獨立地變化。
 *
 *  橋接模式書中舉得例子是MN兩個品牌的手機,安裝兩個不一樣的遊戲,開始寫的話可能就須要寫
 *  M裏邊有兩個遊戲屬性,N裏邊有兩個遊戲屬性,這樣再有十個手機品牌的話,每一個手機品牌就要
 *  寫兩個手機屬性。算下來就是寫了二十個手機屬性,
 *  如今呢,咱們把手機單獨分離出來,把遊戲也分離出來,給手機添加一個加載遊戲的方法,醬紫
 *  的話遊戲就須要聲明一遍就能夠了。
 */
- (void)bridgePattern{
    TFQPhoneM *M = [[TFQPhoneM alloc] init];
    TFQPhoneN *N = [[TFQPhoneN alloc] init];
    TFQPhoneGameA *gameA = [[TFQPhoneGameA alloc] init];
    TFQPhoneGameB *gameB = [[TFQPhoneGameB alloc] init];
    [M setPhoneGame:gameA];
    [M run];
    [M setPhoneGame:gameB];
    [M run];
    [N setPhoneGame:gameA];
    [N run];
}

#pragma mark - 單例模式
/**
 *  單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點
 *
 *  單例模式這種吊炸天的東西,你們應該都有使用,最簡單的方法就是dispatch_once建立,
 *  可是這種方法建立必須調用對應的類方法,若是用alloc 或者copy建立的話,仍是會建立
 *  一個新對象,這時候你們就要重寫copywithzone方法,這個你們自行百度吧。
 *  可是本身用的話,來一個類方法就已經夠用了。本身雪薇注意一下就能夠了。
 *  涉及到java的懶漢式單例,餓漢式單例。
 */
- (void)sigletonPattern{
    //你們能夠打印一下試試  我記得onceToken初始化是0  執行以後變爲1就不再執行了。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //do something create once
    });
}

#pragma mark - 迭代器模式
/**
 *  迭代器模式:提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部表示
 *
 *  書中舉得例子是while循環,知道循環結束,while中止。
*   簡單來講就是for循環,把iOS的幾種循環列舉一下得了。具體的效率問題你們能夠本身個兒百度去。
 */
- (void)iteratorPattern{
    for(int i=0; i<10; i++){
        NSLog(@"=%d",i);
    }
    NSArray *array = @[@1,@2,@3,@4];
    for(NSNumber *i in array){
        NSLog(@"==%@",i);
    }
    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"===%@",obj);
    }];
}


#pragma mark - 組合模式
/**
 *  組合模式:
 *
 *  組合模式簡直是一個吊炸天的設計模式,有那麼點遞歸的意思。
 *
 *  書中的例子是寫了一個大公司的OA系統,可是大公司下邊還有子公司,子公司還要子公司,這時候組合模式的
 *  好處就體現的淋漓盡致。
 *                                 -HR
 *                     -HR         -財務     -HR
 *  下邊代碼的結構  -北京 -石家莊分公司 -橋西分公司-財務
 *                     -財務        -橋東分公司-HR
 *                                          -財務
 */
- (void)combinatorialPattern{
    TFQConcreteCompany *beijingCompany = [[TFQConcreteCompany alloc] initWithName:@"北京總公司"];
    TFQHRDepartment *beijingHR = [[TFQHRDepartment alloc] initWithName:@"北京HR"];
    TFQMoneyDepartment *beijingMoney = [[TFQMoneyDepartment alloc] initWithName:@"北京財務"];
    [beijingCompany add:beijingHR];
    [beijingCompany add:beijingMoney];
    
    TFQConcreteCompany *shijiazhuangCompany = [[TFQConcreteCompany alloc] initWithName:@"石家莊分公司"];
    [beijingCompany add:shijiazhuangCompany];
    TFQHRDepartment *shijiazhuangHR = [[TFQHRDepartment alloc] initWithName:@"石家莊HR"];
    TFQMoneyDepartment *shijiazhuangMoney = [[TFQMoneyDepartment alloc] initWithName:@"石家莊財務"];
    [shijiazhuangCompany add:shijiazhuangHR];
    [shijiazhuangCompany add:shijiazhuangMoney];
    
    TFQConcreteCompany *qiaodongCompany = [[TFQConcreteCompany alloc] initWithName:@"石家莊橋東分公司"];
    [shijiazhuangCompany add:qiaodongCompany];
    TFQHRDepartment *qiaodongHR = [[TFQHRDepartment alloc] initWithName:@"石家莊橋東HR"];
    TFQMoneyDepartment *qiaodongMoney = [[TFQMoneyDepartment alloc] initWithName:@"石家莊橋東財務"];
    [qiaodongCompany add:qiaodongHR];
    [qiaodongCompany add:qiaodongMoney];
    
    TFQConcreteCompany *qiaoxiCompany = [[TFQConcreteCompany alloc] initWithName:@"石家莊橋西分公司"];
    [shijiazhuangCompany add:qiaoxiCompany];
    TFQHRDepartment *qiaoxiHR = [[TFQHRDepartment alloc] initWithName:@"石家莊橋西HR"];
    TFQMoneyDepartment *qiaoxiMoney = [[TFQMoneyDepartment alloc] initWithName:@"石家莊橋西財務"];
    [qiaoxiCompany add:qiaoxiHR];
    [qiaoxiCompany add:qiaoxiMoney];
    
    //打印結構圖
    [beijingCompany displayCompanyWithCount:1];
}

#pragma mark - 備忘錄模式
/**
 *  備忘錄模式:在不破壞封裝性的前提下,捕獲一個對象的內部狀態,並在該對象以外保存這個狀態。
 *  這樣之後就可將該對象恢復到原先保存的狀態。
 *
 *  我只能說,雞肋,哈哈哈,就是用第三方類保存了對應的屬性而已。
 *  寫個例子,打遊戲保存血量跟藍量
 *  其實這些個涉及模式中,每一個設計模式都有管理者類,寫法更加嚴謹,可是我就是不想寫管理者類。
 */
- (void)mementoPattern{
    TFQGamePlayer *player = [[TFQGamePlayer alloc] init];
    player.blood = @"100";
    player.chaKeLa = @"100";
    TFQRecord *record = [[TFQRecord alloc] init];
    [record saveWithPlayer:player];
    NSLog(@"打仗前血量:%@ 查克拉:%@",player.blood,player.chaKeLa);
    player.blood = @"90";
    player.chaKeLa = @"90";
    NSLog(@"打仗後血量:%@ 查克拉:%@",player.blood,player.chaKeLa);
    [record resurrectionWithPlayer:player];
    NSLog(@"恢復進度後血量:%@ 查克拉:%@",player.blood,player.chaKeLa);
}

#pragma mark - 適配器模式
/**
 *  適配器模式:將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得本來因爲接口不兼容
 *  而不能一塊兒工做的那些類能夠一塊兒工做。
 *
 *  其實你們實際開發中確定都用過適配器模式,我也用過,原來的老代碼有一部分不敢動,可是又有新需求,
 *  只好小小的適配一下,可是那時候用的時候,並不知道這是一個設計模式。
 *
 *  書中的例子說的是姚明剛去NBA工做,不懂英語,沒法合理的理解戰術,這時候就須要一個翻譯來告訴
 *  姚明須要作些什麼,適配器的很好提現,通俗易懂。
 */
- (void)adapterPattern{
    TFQNBAPlayer *kobe = [[TFQNBAKobe alloc] initWithName:@"kobe"];
    [kobe attack];
    TFQNBAPlayer *translater = [[TFQTranslater alloc] initWithName:@"yaoming"];
    [translater defense];
}

#pragma mark - 狀態模式
/**
 *  狀態模式:當一個對象的內在狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。
 *
 *  書中的例子是小菜加班,上午精神飽滿,中午吃飯午休,下午困,幹完活就能夠正點下班,
 *  幹不完活兒,就只能繼續加班。這一天的各類狀態是以時間判斷的,這裏邊至少要寫五、6個if else
 *  語句,之後再作修改就會至關費勁,因此引入了狀態模式。
 *
 *  狀態模式的巨大優勢就是隔離了變化,改了那個狀態一目瞭然別的狀態不用管,可是狀態模式優勢繞。須要
 *  手動實現如下,哪怕是實現一個demo也好
 */
- (void)statePattern{
    TFQWork *work = [[TFQWork alloc] init];
    work.hour = 9;
    [work writeCode];
    work.hour= 13;
    [work writeCode];
    work.hour = 23;
    [work writeCode];
}

#pragma mark - 抽象工廠模式
/**
 *  抽象工廠模式:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
 *  java裏邊的接口,iOS這裏所有用繼承來實現。
 *
 *  先來一波抽象工廠的文字解釋,書中的例子就是數據庫從sqlserver 切換到了 access數據庫,致使大部分代碼須要重寫。
 *  那是怎麼解決這個問題的呢?
 *  從源頭上就開始寫抽象工廠,而後實例化sqlserver、access兩個子類,這樣子前期工做量大一點,可是後期切換起來方便。
 *  可是這個東西,我只能大致的跟你們演練一下,說到底我感受這也是個雞肋的設計模式。
 *
 *  java裏邊用到了反射,iOS裏邊怎麼解決這個棘手的問題呢。雪薇有點尷尬。 難道要用NSClassFromString?
 */
- (void)abstraceFactoryPattern{
    //若是想用數據庫,只須要修改這裏的屬性值就能夠了
    TFQDataBaseManager.databaseName = @"sqlserver";
    //TFQDataBaseManager.databaseName = @"oracle";
    TFQDataBase *database = [TFQDataBaseManager getDataBase];
    [database connectDB];
    TFQCRUD *crud = [TFQDataBaseManager getCRUD];
    [crud crud];
}

#pragma mark - 觀察者模式
/**
 *  建造者模式:定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,
 *  會通知全部的觀察者對象,使他們可以自動更新本身。
 *
 *  java 中有一個委託事件 public event EventHandler update; ios 裏邊沒有,這裏用通知實現。
 *  可是用通知實現起來沒什麼意思,每天寫通知,都快寫爛了,可是那又有什麼辦法呢。
 *  iOS用通知強硬的實現觀察者模式,哈哈哈,其實更形象的觀察者模式是kvo,你們能夠研究一下,其實精髓就是建造子類重寫了set方法。
 */
- (void)oberverPattern{
    TFQNotification *notification = [[TFQNotification alloc] init];
    TFQObserver1 *observer1 = [[TFQObserver1 alloc] init];
    TFQObserver2 *observer2 = [[TFQObserver2 alloc] init];
    //監聽通知
    [[NSNotificationCenter defaultCenter] addObserver:observer1 selector:@selector(receiveNotifacation) name:@"1" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:observer2 selector:@selector(receive) name:@"2" object:nil];
    
    //建立通知
    NSNotification *no1 = [[NSNotification alloc] initWithName:@"1" object:nil userInfo:nil];
    NSNotification *no2 = [[NSNotification alloc] initWithName:@"2" object:nil userInfo:nil];
    [notification.notifications addObject:no1];
    [notification.notifications addObject:no2];
    
    //發送通知
    [notification sendNotification];
    
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:observer1];
    [[NSNotificationCenter defaultCenter] removeObserver:observer2];
}

#pragma mark - 建造者模式
/**
 *  建造者模式:將一個複雜的對象的構建與他的表示分離,使得一樣的構建過程能夠建立不一樣的表示。
 *
 *  書中的例子是用代碼畫小人兒,畫完胖的畫瘦的,可是有時候可能會忘記畫一條腿,爲了不這種錯誤就出現了建造者模式
 *  建造者模式在java裏邊其實就是建立了一個抽象類,讓子類繼承他必須實現某些方法。這樣就不會少調用東西。
 *  可是iOS裏邊沒有抽象類怎麼實現呢?那就只能在父類方法實現體裏邊寫輸出語句或者alert語句,醬紫少實現方法就會提示你,
 *  可是這個方法只能再運行的時候提示你,沒辦法,誰讓iOS沒有抽象類的概念呢。
 *  裏邊有一個指揮者類,用它來控制建造過程,也用他來隔離用戶與建造過程的關聯,我的感受沒什麼卵用
 *  其實父類裏邊的這個build方法就是至關於這個指揮者類的功能,本人感受再寫個指揮者類會代碼冗餘,就直接寫到父類裏了
 *
 *  下邊開始畫小人兒
 */
- (void)builderPattern{
    TFQBuilderA *buildA = [[TFQBuilderA alloc] init];
    [buildA beginBuild];
    
    TFQBuilderB *buildB = [[TFQBuilderB alloc] init];
    [buildB beginBuild];
}

#pragma mark - 外觀模式
/**
 *  外觀模式:爲子系統中的一組接口提供一個一致的界面,此模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
 *
 *  我的理解:外觀模式就是迪米特法則的正式運用。讓一個第三方的類去給你管理其餘的類,你不須要知道其餘類的具體實現。
 *  書中的例子是,新股民須要買多支股票,就須要瞭解多支股票的信息,可是若是新股民找一個管理人的話,那麼新股民就
 *  不須要了解股票的具體信息,把錢直接給這個管理人,等着拿利息就好了。
 *
 */
- (void)appearancePattern{
    TFQFund *fund = [[TFQFund alloc] init];
    [fund buy];
    [fund sell];
}

#pragma mark - 迪米特法則
/**
 *  迪米特法則(也叫最少知識原則):若是兩個類沒必要彼此直接通訊,那麼這兩個類就不該當發生直接的相互做用。若是其中一個
 *  類須要調用另外一個類的某一個方法的話,能夠經過第三者轉發這個調用。   強調了類之間的鬆耦合。
 *
 *  拿書中的例子來講,小菜入職須要去運維部門配置電腦,可是沒必要要直接找到運維部門的小張去配置電腦,直接找到運維部門兒的
 *  領導說:我要配置電腦,這時候領導叫小張去給你配置電腦,若是小張有事兒,領導還能夠指派小李給你配置電腦。耦合性下降。
 *
 *  類之間的耦合越弱,越有利於複用。
 */


#pragma mark - 模板方法模式
/**
 *  模板方法模式:定義一個操做中的算法的骨架,而將一些步驟延遲到子類中,模板方法使得一些子類能夠不改變
 *  一個算法的結構便可衝定義該算法的某些特定步驟
 *
 *  模板方法就是用簡單的繼承才作一些操做。
 *  書中的例子就是老師在黑板上出試卷,學生ABC須要把題目抄下來而後答題,若是學生ABC把題目都抄一遍的話題目可能會抄錯,
 *  並且浪費時間,因此就要用一個父類來存放試卷,這時候就要儘量的減小相同代碼的書寫,儘可能寫一次。把不變的代碼作好封裝。
 */
- (void)templateMethodPattern{
    TFQTestPaperA *testPaperA = [[TFQTestPaperA alloc] init];
    [testPaperA answerQuestion];
    TFQTestPaperB *testPaperB = [[TFQTestPaperB alloc] init];
    [testPaperB answerQuestion];
}

#pragma mark - 原型模式
/**
 *  原型模式:用原型實例指定建立對象的種類,而且經過拷貝政協原型建立新的對象。
 *  原型模式用到了java的重要知識拷貝對象,並且是深拷貝,Java中須要實現Cloneable接口,在clone方法中進行操做。可是不過OC更偏向於Java這種
 *  方式,OC中若是一個對象須要被拷貝,他須要實現協議:<NSCopying>、<NSMutableCopying>從名字上咱們能夠看到,一個協議是用於不可變對象的,
 *  一個協議適用於可變對象的
 */
- (void)prototypePattern{
    TFQCopyObject *copyObject = [[TFQCopyObject alloc] init];
    copyObject.name = @"1";
    copyObject.array = @[@1,@"2"];
    NSLog(@"%@,%@",copyObject.name,copyObject.array);
    TFQCopyObject *copyObject2 = [copyObject copy];
    copyObject2.name = @"老鐵";
    copyObject2.array = @[@4,@"hello world"];
    NSLog(@"%@,%@",copyObject2.name,copyObject2.array);
}


#pragma mark - 工廠方法模式
/**
 *  工廠方法模式:定義一個用於建立對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。
 *  工廠方法的精髓是擴展性極強,並且不影響原來的邏輯。
 *  書中例子的雷鋒工廠是用接口實現的,可是OC裏邊沒有接口,只好用父類來曲線救國了
 *
 *  書中的例子是學雷鋒,如今有學雷鋒的學生、志願者,
 *  若是用簡單工廠模式:
 *     那就是建立如下類。須要幫助的老奶奶、學雷鋒父類、學雷鋒學生子類、學雷鋒志願者子類4個類。
 *  若是是工廠方法模式:
 *     須要建立老奶奶、學雷鋒父類、學雷鋒工廠、學雷鋒學生工廠、學雷鋒學生、學雷鋒志願者工廠、學雷鋒志願者6個類。
 *  下邊比上邊多了兩個工廠類,可是修改起來那簡直就是很舒服了,簡單易操做,易理解。只須要改一個地方。
 *
 */
- (void)factoryMethodPattern{
    //若是要換人的話那麼只須要改動這一個地方便可:TFQStudentFactory替換爲TFQVolunteerFactory就變成了志願者學雷鋒了
    TFQLeiFengFactory *factory = [[TFQStudentFactory alloc] init];
    TFQLeiFeng *leiFeng = [factory createLeiFeng];
    [leiFeng sweep];
    [leiFeng wash];
}



#pragma mark - 代理模式
/**
 *  代理模式:爲其餘對象提供一種代理以控制對這個對象的訪問。
 *  A經過B達到與C溝通的目的,這就是代理模式。 AB須要實現同一個接口,看起來是B與C溝通,其實B的方法內部都是A的操做,簡介實現了
 *  A與C的溝通。
 *  這裏的代理其實理念上跟iOS的代理是同樣的,只不過iOS的代理是一個弱引用delegate,沒有B這個第三方。
 *
 *  既然OC裏邊沒有接口這個概念,那麼只好用繼承來實現了
 *  例子還用書中的例子,A經過B追求C,追求方式是送禮物
 *
 */
- (void)proxyPattern{
    TFQGirlC *girl = [[TFQGirlC alloc] initWithName:@"小芳"];
    TFQGiftB *giftB = [[TFQGiftB alloc] initWithGirl:girl];
    [giftB sendFlower];
    [giftB sendChocolate];
}

#pragma mark - 裝飾模式
/**
 *  裝飾模式:動態地給一個對象添加一些額外的職責,就增長功能來講,裝飾模式比生成子類更爲靈活。
 *  裝飾模式用到了一個java的重要知識,構造方法:與類同名沒有返回值。
 *
 *  大話涉及模式中舉的例子是穿衣服的問題,利用構造方法作一些手腳,把A的子類B的屬性賦值到A的子類C中,實現了屬性傳遞。
 *  那咱們OC裏邊怎麼辦呢,用init 方法,替換了書中例子中的new操做 跟Decorate操做。
 *
 *  咱們繼續搞穿衣服的例子   person:人類   decorator:服飾父類。 其他的爲服飾子類。
 *  寫完以後我的感受裝飾模式做用不太大,可能應用場景比較苛刻。不過簡直寫完是真的很舒服,對繼承理解的更深入了。
 *  show方法這裏可能比較繞,你們能夠根據方法一行一行捋代碼,捋完以後恍然大悟。也能夠用笨辦法,把繼承的show方法所有在當前子類中重寫一遍。
 *  這樣看起來就比較好理解了。很舒服。
 */
- (void)DecorativePattern{
    TFQPerson *person = [[TFQPerson alloc] initWithName:@"張三"];
    TFQHat *hat = [[TFQHat alloc] initWithPerson:person];
    TFQShoes *shoes = [[TFQShoes alloc] initWithPerson:hat];
    [shoes show];
}

#pragma mark - 依賴倒轉原則
/**
 *  依賴倒轉原則:高層模塊不該該依賴底層模塊
 *
 */


#pragma mark - 開放-封閉原則
/**
 *  開放-封閉原則: 軟件實體(類、模塊、函數等等)應該能夠擴展,可是不可修改
 *  當前實體內部應該儘可能少修改,可是改實體擴展性要好
 */

#pragma mark - 單一職責原則
/**
 *  單一職責原則: 就一個類而言,應該僅有一個引發它變化的緣由
 *  這個解釋能夠說是通俗易懂了:高內聚低耦合
 */

#pragma mark - StrategyPattern 策略模式
/**
 *  策略模式舉的例子是 商場打折、滿減、滿贈活動,其實在我看來就是一個封裝,取了一個裝逼的名字而已,
 *  而後這裏講解的例子是把策略模式跟工廠模式結合來實現計算器,其實就是找了一箇中間類,把「變化」封裝到這個中間類而已。
 */
- (void)strategyPattern{
    [TFQStraTegy getResultWithText:self.textField.text];
}

#pragma mark - FactoryPattern 簡單工廠模式
/**
 *  簡單工廠模式舉的例子是 計算器的實現,很好的詮釋了封裝、集成、多態的用法。
 */
- (void)factoryPattern{
    [self calculateResult];
}

- (void)calculateResult{
    NSString *str = self.textField.text;
    TFQOperation *operation;
    NSString *flag;
    if([str containsString:@"+"]){
        flag = @"+";
        operation = [[TFQAdd alloc] init];
    }else if([str containsString:@"-"]){
        flag = @"-";
        operation = [[TFQSubtract alloc] init];
    }else if([str containsString:@"*"]){
        flag = @"*";
        operation = [[TFQMultiply alloc] init];
    }else if([str containsString:@"/"]){
        flag = @"/";
        operation = [[TFQDivide alloc] init];
    }else{
        NSLog(@"輸入錯誤");
        return;
    }
    int location = (int)[str rangeOfString:flag].location;
    operation.numA = [[str substringToIndex:location] intValue];
    operation.numB = [[str substringFromIndex:location+1] intValue];
    float result = [operation getResult];
    NSLog(@"%d%@%d = %.2f",operation.numA,flag,operation.numB,result);
}
複製代碼
相關文章
相關標籤/搜索