裝飾模式是在不必改變原類文件和使用繼承的情況下熊响,動態(tài)地擴展一個對象的功能诗赌。它是通過創(chuàng)建一個包裝對象秸弛,也就是裝飾來包裹真實的對象递览。
比如游戲機有一個GamePad類, 現(xiàn)在要增加一個作弊功能(例如100條命), 如果直接在GamePad類中去添加可能會影響其他子類的使用
我們考慮裝飾模式思維, 先建立一個裝飾器實現(xiàn)GamePad的所有功能, 然后在裝飾器類的子類中去添加作弊放方法
上代碼
比如GamePad類是這樣
#import <Foundation/Foundation.h>
@interface GamePad : NSObject
- (void)up;
- (void)down;
- (void)left;
- (void)right;
- (void)buttonA;
- (void)buttonB;
@end
我們創(chuàng)建一個裝飾器類, 讓它持有一個GamePad實例并實現(xiàn)相同的方法接口
GamePadDecorator.h
#import <Foundation/Foundation.h>
#import "GamePad.h"
@interface GamePadDecorator : NSObject
- (void)up;
- (void)down;
- (void)left;
- (void)right;
- (void)buttonA;
- (void)buttonB;
@end
GamePadDecorator.m
#import "GamePadDecorator.h"
@interface GamePadDecorator ()
@property (nonatomic, strong) GamePad *gamePad;
@end
@implementation GamePadDecorator
- (instancetype)init {
self = [super init];
if (self) {
self.gamePad = [[GamePad alloc] init];
}
return self;
}
- (void)up {
[self.gamePad up];
}
- (void)down {
[self.gamePad down];
}
- (void)left {
[self.gamePad left];
}
- (void)right {
[self.gamePad right];
}
- (void)buttonA {
[self.gamePad buttonA];
}
- (void)buttonB {
[self.gamePad buttonB];
}
@end
現(xiàn)在我們新增一個子類來實現(xiàn)作弊方法
CheatGamePadDecorator.h
#import "GamePadDecorator.h"
@interface CheatGamePadDecorator : GamePadDecorator
- (void)cheat;
@end
CheatGamePadDecorator.m
#import "CheatGamePadDecorator.h"
@implementation CheatGamePadDecorator
- (void)cheat {
NSLog(@"cheat");
}
@end
這樣我們就可以直接在Controller中直接用CheatGamePadDecorator類去實現(xiàn)GamePad的所有功能還能額外實現(xiàn)作弊方法
#import "ViewController.h"
#import "CheatGamePadDecorator.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//創(chuàng)建CheatGamePadDecorator實例
CheatGamePadDecorator *cheaterGamePad = [[CheatGamePadDecorator alloc] init];
//實現(xiàn)GamePad的功能
[cheaterGamePad up];
[cheaterGamePad down];
//實現(xiàn)作弊方法
[cheaterGamePad cheat];
}
@end
這樣就完成了一個裝飾模式思路的代碼構建
下面說說cocoa touch中自帶的Category, 它也是對裝飾模式的一個實現(xiàn)
我們用Category來實現(xiàn)上面GamePad添加作弊功能
我們創(chuàng)建一個Cheat Category
GamePad+Cheat.h
#import "GamePad.h"
@interface GamePad (Cheat)
- (void)cheat;
@end
GamePad+Cheat.m
#import "GamePad+Cheat.h"
@implementation GamePad (Cheat)
- (void)cheat {
NSLog(@"cheat");
}
@end
這樣我們就可以直接在Controller中通過Category來實現(xiàn)上面功能
#import "ViewController.h"
#import "GamePad+Cheat.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//創(chuàng)建GamePad實例
GamePad *gamePad = [[GamePad alloc] init];
//實現(xiàn)GamePad原有方法
[gamePad up];
[gamePad down];
//實現(xiàn)作弊方法
[gamePad cheat];
}
使用Category更為簡單
但是在使用Category時有個細節(jié)一定要注意, 盡量不要在Category類中去重寫基類方法
假如我們在GamePad+Cheat.h中重寫了- (void)up方法, 則整個工程中的up方法都被重載了
即使我們不在任何地方引用GamePad+Cheat.h, 只要這個文件在工程里面就會讓GamePad方法被重載