当别人问起我们用过什么设计模式时,很多人可能第一反应会很茫然。其实我们一直都在使用着,只是我们没有刻意的去定义哪种方式是什么设计模式而已。其实我觉得设计模式更重要的是一种思维,而不是一点要具体提现在哪段代码中。这样说,可能还不是说的很明确,但是很多人在写程序的时候,应该用到过代理、类别等等吧?这些就是一种设计模式,接下来我就简单介绍一下,一些基本的设计模式。
一 MVC模式
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
通常模型对象负责在数据库中存取数据。
通常视图是依据模型数据创建的。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC的优点:
1、可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。
2、视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。
3、模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
4、潜在的框架结构。可以基于此模型建立应用程序框架,不仅仅是用在设计界面的设计中。
MVC的不足之处:
1、增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
2、视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
3、视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
4、目前,一般高级的界面工具或构造器不支持模式。改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,从而造成MVC使用的困难。
二 单例模式
单例模式用于当一个类只能有一个实例的时候,就像它的名字一样,意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
单例模式的注意事项:
1.某个类只能有一个实例;
2.必须自行创建这个实例;
3.必须自行向整个系统提供这个实例。
单例模式的优点:
1.实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例。
static SingletonDesign *singletonDesign = nil;
<pre name="code" class="objc" style="color: rgb(17, 17, 17); line-height: 23.3999996185303px;">//第一步:<span style="color: rgb(17, 17, 17); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 23.3999996185303px;">静态实例,并初始化。</span>
<span style="color: rgb(17, 17, 17); font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 23.3999996185303px;">//第二步:实例构造检查静态实例是否为nil</span>
+ (SingletonDesign *) shareInstance{ if (singletonDesign == nil) { singletonDesign = [[super allocWithZone:NULL] init]; } return singletonDesign;}/* 上面这种方式是标准的创建单例的方式。但是我们不能保证,其他人在不知道这个类是单例的情况下,通过其它方式创建。比如:alloc、allocWithZone、new等。 所以我们还需要重写如下方法。 */+ (id)allocWithZone:(struct _NSZone *)zone{ return [self shareInstance];}+ (id)new{ return [self alloc];}+ (id)alloc{ return nil;}
三 装饰器(Decorator)模式
装饰起模式在不修改原来代码的情况下动态的给对象增加新的行为和功能,它通过一个对象包装被装饰对象的方法来修改类的行为,这种方法可以做为子类化的一种替代方法。
在iOS中,存在两种非常常见的实现:Category(类别)和Delegation(代理)。
如果有对类别和代理不清楚的可以自己去看一下官方文档,或者找一下度娘,这里就不详细介绍了。
四 观察者模式
1.Notification
Notification - NotificationCenter机制使用了操作系统的功能。通过NSNotificationCenter可以让对象之间进行进行通讯,这些对象相互间可以不认识。当你用一个并行的流来推送通知,或者刷新数据库,并希望在界面中能够看到时,这非常有用。
NotificationCenter发布消息的方法如下所示:
NSNotification * broadcastMessage = [ NSNotification notificationWithName: AnyNotification object: Self ];
NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter];
[NotificationCenter postNotification: broadCastMessage];
上面的代码中,创建了一个NSNotification类型的对象,并指定名称为”broadcastMessage”,然后通过notificationCenter来发布这个消息。
要订阅感兴趣的对象中的相关事件,可以按照如下方法进行:
NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter];
[NotificationCenter addObserver: Self selector: @ selector (update:) name: AnyNotification object: nil ];
如上代码所示:订阅了一个事件,并通过@selector指定了一个方法。
// 收到通知中心发来的通知
-(void)update:(NSNotification *) notification
{
if ([[notification name] isEqualToString:AnyNotification])
NSLog (@"成功收到通知中心发来的名为%@的通知", AnyNotification);
}
2.KVO
通过KVO,某个对象中的特定属性发生了改变,别的对象可以获得通知。苹果官方文档对KVO有了很好的解释:Key-Value Observing Programming Guide。下面两种方法都可以改变对象中属性的值:
kvoSubj.changeableProperty = @"新的一个值";
[kvoSubj setValue:@"新的一个值" forKey:@"changeableProperty"];
上面这种值改变的灵活性可以让我们对键值进行观察。
下面是新建的一个类KVOSubject,这个类中有一个属性changeableProperty:
@interface KVOSubject : NSObject
@property (nonatomic, strong) NSString *changeableProperty;
@end
@implementation KVOSubject
@end
接着新建了另外一个类KVOObserver,通过该类可以监听changeableProperty属性值的改变。
@interface KVOObserver : NSObject
@end
@implementation KVOObserver
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"KVO:值发生了改变");
}
@end
如上代码所示,KVOObserver类只有一个方法observeValueForKeyPath。当changeableProperty属性值的改变时,这个方法会被调用。下面是测试的代码:
- (IBAction)btnKVOObservationTest:(id)sender {
KVOSubject *kvoSubj = [[KVOSubject alloc] init];
KVOObserver *kvoObserver = [[KVOObserver alloc] init];
[kvoSubj addObserver:kvoObserver forKeyPath:@"changeableProperty" options:NSKeyValueObservingOptionNew conte xt:nil];
kvoSubj.changeableProperty = @"新的一个值";
[kvoSubj setValue:@"新的一个值" forKey:@"changeableProperty"];
[kvoSubj removeObserver:kvoObserver forKeyPath:@"changeableProperty"];
}
执行上面的代码,可以看到控制台输出如下结果:
2013-05-05 23:10:20.789 ObserverPattern[1358:c07] KVO:值发生了改变
2013-05-05 23:10:20.790 ObserverPattern[1358:c07] KVO:值发生了改变标准方法
五 工厂模式
可以根据以下两篇文章来理解。
http://blog.csdn.net/xiazailushang/article/details/19040117
http://www.2cto.com/kf/201402/280586.html
六 适配器模式(Adapter)
具体可以参考这篇文章:
http://www.2cto.com/kf/201312/266339.html
七 策略模式