裝飾模式是在不必改變原類文件和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對象的功能。它是通過創(chuàng)建一個(gè)包裝對象,也就是裝飾來包裹真實(shí)的對象。
比如游戲機(jī)有一個(gè)GamePad類, 現(xiàn)在要增加一個(gè)作弊功能(例如100條命), 如果直接在GamePad類中去添加可能會(huì)影響其他子類的使用
我們考慮裝飾模式思維, 先建立一個(gè)裝飾器實(shí)現(xiàn)GamePad的所有功能, 然后在裝飾器類的子類中去添加作弊放方法
上代碼
比如GamePad類是這樣
1 #import <Foundation/Foundation.h> 2 3 @interface GamePad : NSObject 4 5 - (void)up; 6 - (void)down; 7 - (void)left; 8 - (void)right; 9 - (void)buttonA; 10 - (void)buttonB; 11 12 @end
我們創(chuàng)建一個(gè)裝飾器類, 讓它持有一個(gè)GamePad實(shí)例并實(shí)現(xiàn)相同的方法接口
GamePadDecorator.h
1 #import <Foundation/Foundation.h> 2 #import "GamePad.h" 3 4 @interface GamePadDecorator : NSObject 5 6 - (void)up; 7 - (void)down; 8 - (void)left; 9 - (void)right; 10 - (void)buttonA; 11 - (void)buttonB; 12 13 @end
GamePadDecorator.m
1 #import "GamePadDecorator.h" 2 3 @interface GamePadDecorator () 4 5 @property (nonatomic, strong) GamePad *gamePad; 6 7 @end 8 9 @implementation GamePadDecorator 10 11 - (instancetype)init { 12 self = [super init]; 13 if (self) { 14 self.gamePad = [[GamePad alloc] init]; 15 } 16 return self; 17 } 18 19 - (void)up { 20 [self.gamePad up]; 21 } 22 23 - (void)down { 24 [self.gamePad down]; 25 } 26 27 - (void)left { 28 [self.gamePad left]; 29 } 30 31 - (void)right { 32 [self.gamePad right]; 33 } 34 35 - (void)buttonA { 36 [self.gamePad buttonA]; 37 } 38 39 - (void)buttonB { 40 [self.gamePad buttonB]; 41 } 42 43 @end
現(xiàn)在我們新增一個(gè)子類來實(shí)現(xiàn)作弊方法
CheatGamePadDecorator.h
1 #import "GamePadDecorator.h" 2 3 @interface CheatGamePadDecorator : GamePadDecorator 4 5 - (void)cheat; 6 7 @end
CheatGamePadDecorator.m
1 #import "CheatGamePadDecorator.h" 2 3 @implementation CheatGamePadDecorator 4 5 - (void)cheat { 6 NSLog(@"cheat"); 7 } 8 9 @end
這樣我們就可以直接在Controller中直接用CheatGamePadDecorator類去實(shí)現(xiàn)GamePad的所有功能還能額外實(shí)現(xiàn)作弊方法
1 #import "ViewController.h" 2 #import "CheatGamePadDecorator.h" 3 4 @interface ViewController () 5 6 @end 7 8 @implementation ViewController 9 10 - (void)viewDidLoad { 11 [super viewDidLoad]; 12 13 //創(chuàng)建CheatGamePadDecorator實(shí)例 14 CheatGamePadDecorator *cheaterGamePad = [[CheatGamePadDecorator alloc] init]; 15 16 //實(shí)現(xiàn)GamePad的功能 17 [cheaterGamePad up]; 18 [cheaterGamePad down]; 19 20 //實(shí)現(xiàn)作弊方法 21 [cheaterGamePad cheat]; 22 } 23 24 25 26 @end
這樣就完成了一個(gè)裝飾模式思路的代碼構(gòu)建
下面說說cocoa touch中自帶的Category, 它也是對裝飾模式的一個(gè)實(shí)現(xiàn)
我們用Category來實(shí)現(xiàn)上面GamePad添加作弊功能
我們創(chuàng)建一個(gè)Cheat Category
GamePad+Cheat.h
1 #import "GamePad.h" 2 3 @interface GamePad (Cheat) 4 5 - (void)cheat; 6 7 @end
GamePad+Cheat.m
1 #import "GamePad+Cheat.h" 2 3 @implementation GamePad (Cheat) 4 5 - (void)cheat { 6 NSLog(@"cheat"); 7 } 8 9 @end
這樣我們就可以直接在Controller中通過Category來實(shí)現(xiàn)上面功能
1 #import "ViewController.h" 2 #import "GamePad+Cheat.h" 3 4 @interface ViewController () 5 6 @end 7 8 @implementation ViewController 9 10 - (void)viewDidLoad { 11 [super viewDidLoad]; 12 13 //創(chuàng)建GamePad實(shí)例 14 GamePad *gamePad = [[GamePad alloc] init]; 15 16 //實(shí)現(xiàn)GamePad原有方法 17 [gamePad up]; 18 [gamePad down]; 19 20 //實(shí)現(xiàn)作弊方法 21 [gamePad cheat]; 22 23 }
使用Category更為簡單
但是在使用Category時(shí)有個(gè)細(xì)節(jié)一定要注意, 盡量不要在Category類中去重寫基類方法
假如我們在GamePad+Cheat.h中重寫了- (void)up方法, 則整個(gè)工程中的up方法都被重載了
即使我們不在任何地方引用GamePad+Cheat.h, 只要這個(gè)文件在工程里面就會(huì)讓GamePad方法被重載