一,什么是装饰模式
- 模式定义
装饰者包含被装饰者的所有接口和引用,方法实现完全是引用调用自己的方法,在装饰者子类添加新功能。
Category不要重写被装饰对象的方法,否则改变了被装饰对象的行为,不符合装饰者模式,只可适用特殊场景。分类主要用于对被装饰者类的方法和属性拓展
- 需求场景
静态库扩展功能。不改变(原始类)、不继承、动态扩展功能。
- 不知道原始类实现细节,只提供接口,动态扩展功能。
- 不想有更多子类,不想通过继承的方式添加功能。
- 动态扩展对象的功能。
- 必须持有对象的引用,包含实例化的被装饰类。
二,装饰模式结构图
实现方式:
- 定义装饰者类,并在.h定义被装饰者类中的所有暴漏到.h的方法(也可以添加自定义的操作方法)和对被装饰者类的引用。
- 在装饰者类用用被装饰者对象对其方法调用,已输出我们想要的结果。
- 如果想拓展被装饰者类,可通过分类的方法,这样可以不破坏被装饰者类原生逻辑。
三,代码示例
- Target(被装饰者类)
- Target.h
@interface Target : NSObject /** * 游戏币的数量 */ @property(nonatomic,assign) NSInteger coin; /** * 上下左右的操作 */ - (void)up; - (void)down; - (void)left; - (void)right; /** * 选择与开始的操作 */ - (void)select; - (void)start; /** * 按钮 A + B 的操作 */ - (void)commandA; - (void)commandB; @end
- Target.m
@implementation Target - (void)up{ NSLog(@"up"); } - (void)down{ NSLog(@"down"); } - (void)left{ NSLog(@"left"); } - (void)right{ NSLog(@"right"); } - (void)select { NSLog(@"select"); } - (void)start { NSLog(@"start"); } - (void)commandA { NSLog(@"commandA"); } - (void)commandB { NSLog(@"commandB"); } @end
- Target.h
- Decorator(装饰者类)
- Decorator.h
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface Decorator : NSObject #pragma mark --被装饰者类方法 @property (nonatomic) NSInteger coin; - (void)up; - (void)down; - (void)left; - (void)right; - (void)select; - (void)start; - (void)commandA; - (void)commandB; #pragma mark - 以下为装饰对象新添加的功能 /** * 剩余几条命 */ @property (nonatomic, readonly) NSInteger lives; /** * 作弊 (上下上下左右左右ABAB) */ - (void)cheat; @end
- Decorator.m
#import "Decorator.h" #import "Target.h" @interface Decorator() @property (nonatomic,strong) Target target; //持有被装饰者类对象 @end @implementation Decorator #pragma mark - 初始化 - (instancetype)init { if (self = [super init]) { // 装饰对象包含一个真实对象的引用 self.target = [Target new]; } return self; } #pragma mark - 让真实对象的引用执行对应的方法 - (void)up { [_target up]; } - (void)down { [_target down]; } - (void)left { [_target left]; } - (void)right { [_target right]; } - (void)select { [_target select]; } - (void)start { [_target start]; } - (void)commandA { [_target commandA]; } - (void)commandB { [_target commandB]; } #pragma mark - 装饰器新添加的方法 - (void)cheat { [_target up]; [_target down]; [_target up]; [_target down]; [_target left]; [_target right]; [_target left]; [_target right]; [_target commandA]; [_target commandB]; [_target commandA]; [_target commandB]; } @synthesize lives = _lives; - (NSInteger)lives { // 相关处理逻辑 return 10; } @end
- Decorator.h
四,装饰模式优缺点
- 优点
在不改变目标类业务逻辑的情况下,拓展原有的方法和功能
五,demo
装饰者模式