设计模式这个东西,感受就跟太极同样,不是固定招式,须要学会而后忘记而后融会贯通。我看《大话设计模式》一书,前先后后大概看了一个月,看完一个本身用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);
}
复制代码