Objective-C 装饰模式--简单介绍和使用
装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
比如游戏机有一个GamePad类, 现在要增加一个作弊功能(例如100条命), 如果直接在GamePad类中去添加可能会影响其他子类的使用
我们考虑装饰模式思维, 先建立一个装饰器实现GamePad的所有功能, 然后在装饰器类的子类中去添加作弊放方法
上代码
比如GamePad类是这样
#import <Foundation/Foundation.h> @interface GamePad : NSObject - (void)up;
- (void)down;
- (void)left;
- (void)right;
- (void)buttonA;
- (void)buttonB; @end
我们创建一个装饰器类, 让它持有一个GamePad实例并实现相同的方法接口
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
现在我们新增一个子类来实现作弊方法
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类去实现GamePad的所有功能还能额外实现作弊方法
#import "ViewController.h"
#import "CheatGamePadDecorator.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; //创建CheatGamePadDecorator实例
CheatGamePadDecorator *cheaterGamePad = [[CheatGamePadDecorator alloc] init]; //实现GamePad的功能
[cheaterGamePad up];
[cheaterGamePad down]; //实现作弊方法
[cheaterGamePad cheat];
} @end
这样就完成了一个装饰模式思路的代码构建
下面说说cocoa touch中自带的Category, 它也是对装饰模式的一个实现
我们用Category来实现上面GamePad添加作弊功能
我们创建一个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来实现上面功能
#import "ViewController.h"
#import "GamePad+Cheat.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; //创建GamePad实例
GamePad *gamePad = [[GamePad alloc] init]; //实现GamePad原有方法
[gamePad up];
[gamePad down]; //实现作弊方法
[gamePad cheat]; }
使用Category更为简单
但是在使用Category时有个细节一定要注意, 尽量不要在Category类中去重写基类方法
假如我们在GamePad+Cheat.h中重写了- (void)up方法, 则整个工程中的up方法都被重载了
即使我们不在任何地方引用GamePad+Cheat.h, 只要这个文件在工程里面就会让GamePad方法被重载
Objective-C 装饰模式--简单介绍和使用的更多相关文章
- Java EE设计模式(主要简单介绍工厂模式,适配器模式和模板方法模式)
Java EE设计模式分为三种类型,共23种: 创建型模式:单例模式.抽象工厂模式.建造者模式.工厂模式.原型模式. 结构型模式:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式 ...
- 嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍
**************************************************************************************************** ...
- dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- 【Dubbo基础】dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- [原创]关于mybatis中一级缓存和二级缓存的简单介绍
关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...
- 利用Python进行数据分析(4) NumPy基础: ndarray简单介绍
一.NumPy 是什么 NumPy 是 Python 科学计算的基础包,它专为进行严格的数字处理而产生.在之前的随笔里已有更加详细的介绍,这里不再赘述. 利用 Python 进行数据分析(一)简单介绍 ...
- yii2的权限管理系统RBAC简单介绍
这里有几个概念 权限: 指用户是否可以执行哪些操作,如:编辑.发布.查看回帖 角色 比如:VIP用户组, 高级会员组,中级会员组,初级会员组 VIP用户组:发帖.回帖.删帖.浏览权限 高级会员组:发帖 ...
- angular1.x的简单介绍(二)
首先还是要强调一下DI,DI(Denpendency Injection)伸手获得,主要解决模块间的耦合关系.那么模块是又什么组成的呢?在我看来,模块的最小单位是类,多个类的组合就是模块.关于在根模块 ...
随机推荐
- 移动web端的react.js组件化方案
背景: 随着互联网世界的兴起,web前端开发的方式越来越多,出现了很多种场景开发的前端架构体系,也对前端的要求日益增高,早已经不是靠一个JQuery.js来做前端页面的时代了,而今移动端变化最大,近 ...
- docker学习之二镜像创建
继上一篇docker入门之后写一点使用的经验. 通过命令:docker run -it REPOSITORY或IMAGE ID 注:-it后面跟的字段可以通过下面指令获得 创建运行的容器,会进入一 ...
- ElasticSearch问题记录
1.Young GC导致集群master重新选举,一台server fail [2016-12-10 07:38:24,546][WARN ][transport ] [BFRD_1] Receive ...
- mac下xampp的mysql无法自动启动
mac下xampp的mysql无法自动启动,每次启动都要手动在终端里执行 sudo /Applications/XAMPP/xamppfiles/bin/mysql.server start 自动启动 ...
- mac 之 jmeter下载、解压、启动
1:下载地址:http://jmeter.apache.org/download_jmeter.cgi 2:双击下载的zip文件,即可解压 3:打开终端,cd 到解压的目录下 例如:cd /User ...
- sql2000分享 批量建表dev_编号
批量建表dev_3970000000014到dev_3970000000035 declare @i bigint declare @j int ) ) ) ) set @sql = '' set @ ...
- python使用pdkdf2加盐密码
from werkzeug.security import generate_password_hash, check_password_hash pw = generate_password_has ...
- SQLServer触发器创建、删除、修改、查看
一: 触发器是一种特殊的存储过程﹐它不能被显式地调用﹐而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活.所以触发器可以用来实现对表实施复杂的完整性约束. 二: SQL Server为每个触发器 ...
- 解决弹出的窗口window.open会被浏览器阻止的问题
问题现象 最近在做项目的时候碰到了使用window.open被浏览器拦截的情况,有时候会一直连接,有时候会偶尔拦截, 尝试了很多方法,走了很多弯路,总结一下结果分享大家 原因分析&深入研究 1 ...
- hibernate不同版本获取获取sessionFactory
hibernate4时,我们采用以下方式获取会话工厂: // 1. 解析我们在hibernate.cfg.xml中的配置 Configuration configuration = new Confi ...