在观察者模式中,一个对象任何状态的变更都会通知另外的对改变感兴趣的对象。这些对象之间不需要知道彼此的存在,这其实是一种松耦合的设计。当某个属性变化的时候,我们通常使用这个模式去通知其它对象。
此模式的通用实现中,观察者注册自己感兴趣的其它对象的状态变更事件。当状态发生变化的时候,所有的观察者都会得到通知。苹果的推送通知(PushNotification)就是一个此模式的例子。
如果你要遵从MVC模式的概念,你需要让模型对象和视图对象在不相互直接引用的情况下通信。这正是观察者模式的用武之地。
Cocoa通过通知(Notifications)和Key-ValueObserving(KVO)来实现观察者模式。
在cocoa框架中的Delegate模式中,委托人往往是框架中的对象(视图中的控件、表视图神马的),代理人往往是视图控制器对象。
在我们这个例子中UITableView是委托人,代理人首先得满足一个条件:就是在.h文件中申明它拥有代理资格:
@interfaceWhateverViewController
其次,在.m文件中定义委托人可以让代理人去代替做的事情:
二、自定义的delegate模式
@interfaceA:UIViewidtransparendValueDelegate;@property(nomatic,retain)idtransparendValueDelegate;@end@implementationA@synthesizetransparendValueDelegate-(void)Call{NSString*value=@"你好";[transparendValueDelegatetransparendValue:value];}@end@interfaceB:UIViewNSString*value;@end@implementationB-(void)transparendValue:(NSString*)fromValue{value=fromValue;NSLog(@"%@,我是B",value);}@end使用时:
A*a=[[Aalloc]init];B*b=[[Balloc]init];a.transparendValueDelegate=b;//设置A代理委托对象为B[aCall];这样就会输出:
你好,我是B
委托模式关键就在于一个“被”字。这个B是很被动的,随时就会被你ACall一下。
三、为什么会有delegate模式
换句话说,它可以用来解决神马问题?
当一个类的某些功能需要被别人来实现,但是既不明确是些什么功能,又不明确谁来实现这些功能的时候,委托模式就可以派上用场。
例如你可以再写个C类,实现-(void)transparendValue:(NSString*)fromValue{NSLog(@"%@,我是C",value);}也是完全可以的。换谁来,只要它实现了这个方法,我就可以委托它来做这个事。
说到底一切都是为了使类之间的耦合性更松散。好的代码应该对扩展开放,对修改关闭。
(二)观察者模式
-(void)dealloc{[self.heroremoveObserver:selfforKeyPath:@"name"];}到了这里观察者模式中常用的KVO及通知的内容就到这里,不过要知道这里谈及的只是最基础的用法,后面我们可能还是有更加深入的探究,或者在后续中可能还会对比iOS中的代理以及Block来探寻下iOS中的消息传递机制,再或者像Swift中的didSet、willSet的属性监听的方法,这些都是很好玩的内容,不是么?(三)MVC模式
MVC根据角色划分类,涉及到三个角色:
Model:模型保存应用程序的数据。
一个MVC模式的好的实现也就意味着每一个对象都会被划分到上面所说的组中。
我们可以很好的用下图来描述通过控制器实现的视图到模型的交互过程:
模型会把任何数据的变更通知控制器,然后控制器更新视图数据。视图对象通知控制器用户的操作,控制器要么根据需要来更新模型,要么检索任何被请求的数据。
你可能在想为什么不能仅仅使用控制器,在一个类中实现视图和模型,这样貌似更加容易?
举个例子来说,如果将来你打算加入电影或者书籍到你的资料库中,你仍然可以使用同样的AlbumView去显示电影和书籍数据。更进一步来说,如果你想创建一个新的与专辑有关联的工程,你可以很简单的复用Album类,因为它不依赖任何视图。这就是MVC的强大之处。
(四)单例模式
单例设计模式确保对于一个给定的类只有一个实例存在,这个实例有一个全局唯一的访问点。它通常采用懒加载的方式在第一次用到实例的时候再去创建它。
注意:苹果大量使用了此模式。例如:[NSUserDefaultsstandardUserDefaults],[UIApplicationsharedApplication],[UIScreenmainScreen],[NSFileManagerdefaultManager],所有的这些方法都返回一个单例对象。
你很可能会想为什么这么关心是否一个类有多个实例?毕竟代码和内存都是廉价的,对吗?
有一些情况下,只有一个实例显得非常合理。举例来说,你不需要有多个Logger的实例,除非你想去写多个日志文件。或者一个全局的配置处理类:实现线程安全的方式访问共享实例是容易的,比如一个配置文件,有好多个类同时修改这个文件。
(五)策略模式
在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(HardCoding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…或者case等条件判断语句来进行选择。这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。如果我们将这些策略包含在客户端,这种做法更不可取,将导致客户端程序庞大而且难以维护,如果存在大量可供选择的算法时问题将变得更加严重。
例子1:一个菜单功能能够根据用户的“皮肤”首选项来决定是否采用水平的还是垂直的排列形式。同事可以灵活增加菜单那的显示样式。
如何让算法和对象分开来,使得算法可以独立于使用它的客户而变化?
策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。
当存在以下情况时使用Strategy模式
Strategy模式有下面的一些优点:
2)提供了可以替换继承关系的办法
3)消除了一些ifelse条件语句
4)实现的选择
Strategy模式缺点:
1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类
2)Strategy和Context之间的通信开销
3)策略模式将造成产生很多策略类
:可以通过使用享元模式在一定程度上减少对象的数量。增加了对象的数目Strategy增加了一个应用中的对象的数目。有时你可以将Strategy实现为可供各Context共享的无状态的对象来减少这一开销。任何其余的状态都由Context维护。Context在每一次对Strategy对象的请求中都将这个状态传递过去。共享的Strategy不应在各次调用之间维护状态。
实例:排序算法,NSArray的sortedArrayUsingSelector;经典的鸭子会叫,会飞案例。
(六)工厂模式
工厂模式我的理解是:他就是为了创建对象的
创建对象的时候,我们一般是alloc一个对象,如果需要创建100个这样的对象,如果是在一个for循环中还好说,直接一句alloc就行了,但是事实并不那么如意,我们可能会在不同的地方去创建这个对象,那么我们可能需要写100句alloc了,但是如果我们在创建对象的时候,需要在这些对象创建完之后,为它的一个属性添加一个固定的值,比方说都是某某学校的学生,那么可能有需要多些100行重复的代码了,那么,如果写一个-(void)createObj方法,把创建对象和学校属性写在这个方法里边,那么就是会省事很多,也就是说我们可以alloc创建对象封装到一个方法里边,直接调用这个方法就可以了,这就是简单工厂方法
代码结构如下
Animal类
@interfaceAnimal:NSObject
@proterty(nonatomic,strong)NSString*name;
-(void)laugh;
@end
Dog类
@interfaceDog:Animal
Cat类
@interfaceCat:Animal
创建对象的工厂类
.h
@interfaceAnimalFactory:NSObject
+(Dog*)createDog;
+(Cat*)createCat;
.m
@implementationAnimalFactory
+(Dog*)createDog{
Dog*dog=[[Dogalloc]init];
dog.name=@“baby”;
returndog;
}
+(Cat*)createCat{
Cat*cat=[[Catalloc]init];
returncat;
Main.m文件
Dog*dog=[AnimalFactorycreateDog];
Cat*cat=[AnimalFactorycreateCat];
这是简单工厂模式
现在创建100个Dog对象,如果这100个对象写在程序中的不同地方,按上边的方法是需要把Dog*dog=[AnimalFactorycreateDog];这一句话写在程序中很多不同的地方,那么现在有一个需求,就是如果需要把这些创建的100个Dog对象全部变成Cat对象,那么按照刚才的那个做法,就需要在这100句代码中把createDog方法变成createCat方法了,这样做还是很复杂
那么这个时候用工厂方法模式就能解决这个难题了
工厂方法模式是为每一个要创建的对象所在的类都相应地创建一个工厂
代码如下
-(Animal*)createAnimal;
@end;
Dog工厂类
@interfaceDogFactory:AnimalFactory;
@implementationDogFactory
-(Animal*)createAnimal{
retrurn[[Dogalloc]init];
Cat工厂类
@interfaceCatFactory:AnimalFactory;
@implementationCatFactory
-(Animal*)createAnimal
retrurn[[Catalloc]init];
Main.m
AnimalFactory*dogFactory=[[DogFactoryalloc]init];
Animal*animal1=[dogFactorycreateAnimal];
[animal1laugh];
Animal*animal2=[dogFactorycreateAnimal];
[animal2laugh];
…….
Animal*animal100=[dogFactorycreateAnimal];
[animal100laugh];
这样话如果要把100个Dog改为Cat的话,只需要吧DogFactory改为CatFactory就可以了
但是工厂方法也有它的限制:
1.要创建的类必须拥有同一个父类
2.要创建的类在100个不同的地方所调用的方法必须一样
以上这些只是个人感悟,会有一些不足的地方,请大家帮忙改正,嘿嘿