原型设计模式
在面向对象的应用程序中,有些对象的创建成本比较高。比如一些数据模型,如果有十几二十个属性,而需要创建的对象和已有的对象只有几项数据不同,这时我们可以复制原有对象,并做轻微的改动,事情就变得相对简单了,使用这种复制操作的模式便是原型模式。
原型模式类图:
图中的HeroModel类实现了PrototypeProtocold定义的复制接口,返回自己的实例对象。
HeroModel模型的实现
1 | @implementation HeroModel |
用原型设计模式实现了简单的复制功能,只是复制后改动相应的属性即可,便创建了一个全新的HeroModel对象。
注意深拷贝和浅拷贝
在使用原型模式的时候需要注意对象的复制操作,如上的示例中就存在一定的隐患。在对象中如果有指针型变量指向了内存中的某个资源时,在复制的时候只复制了指针,那么改变了原型,副本相应的内容也跟着发生了改变,在这里我们就需要使用深拷贝,做好实际资源的复制。如上的实现可改为:
1 |
|
在Cocoa Touch框架也为NSObject的派生类提供了实现复制的协议,使用方法只需遵守
本节工程示例
工厂模式
在创建一些具有相同属性的不同对象的时候,我们可以定制统一的接口行为类,让其子类来指定所生成的具体对象。例如需要生产苹果手机产品,统一定制生产的”协议“,自己可以由自己下面的不同的代工厂生产具体的产品,SE的代工厂生产SE,X生产X。当然需要生产何种产品时交由具体的代工厂来生产。使用工厂模式创建对象比直接创建对象,在给予类变更返回哪一种对象这一点上有更多的灵活性。
工厂模式类图
图中的IPhoneGenerator类定义了返回IPhone对象的接口,其两个子类重载了接口方法,以返回IPhone的实例。
IPhoneSEGenerator的实现
1 | - (IPhone *)creatIPhone |
IPhoneXGenerator的实现
1 | - (IPhone *)creatIPhone |
客户端创建
1 | IPhoneGenerator *generator_X = [[IPhoneXGenerator alloc] init]; |
其中具体生产哪种类型的Iphone由具体的创建者来决定生产。
本节工程示例
抽象工厂模式
同样的电子产品来说,。
抽象工厂类图
图中的IBrandingGenerator类定义了两个返回IPhone对象的接口,其两个子类重载接口方法,以返回IPhone的实例。
BrandingGenerator工厂的实现,在头文件中定义创建APPLE系列还是SAMSUNG系列,具体工厂会依据定义来生成:
1 | + (BrandingGenerator *)generator |
AppleBrandingGenerator工厂的实现
1 | - (TV *)generatorTV |
SamsungBrandingGenerator工厂的实现
1 | - (TV *)generatorTV |
客户端创建
1 | BrandingGenerator *generator = [BrandingGenerator generator]; |
在这种模式下如果需要扩展产品,可在工厂父类中新增接口来支持。另外还可以新增产品系列的支持。
本节工程示例
工厂方法和抽象工厂
相比较之下,这两种方式在创建对象时,都不让客户端知晓到底返回了什么确切的具体对象。工厂模式是通过类继承来创建的抽象产品,并且只能创建单一品种,需要新增子类创建者重载工厂方法来支持新的产品创建。而抽象工厂模式是通过对象组合来创建抽象产品,可以实现多系列的产品创建,需要在父类新增接口来支持新的产品创建。
建造者模式
有些对象的创建比较复杂,一个对象包含很多个部件的组成部分,我们将构建过程拆分成指导者-创建者的模式,客户端直接使用指导者的指导方式进行对象的生成。使用这种构建与它的表现分离模式我们称为建造者模式,也称为生成器模式。
建造者模式类图:
图中的HeroModel类实现了PrototypeProtocold定义的复制接口,返回自己的实例对象。
HeroModel模型的实现
1 | @interface ComputerBuilder () |
使用这种多个步骤、多种方式构建对象,在最后一步返回产品,这个过程比单一创建更容易管理与复用。
本节工程示例
单例模式
在我们开发的应用中,那些只能共享而不能复制的资源,也就是在系统只需存在一份实例,我们可以使用单例模式。例如iOS中的UIApplication、NSUSerDefaults中使用单例模式,只存在单一的访问点。例如我们app的登录用户信息也可以设计为单例模式,持有用户,信息共享。
单例模式类图
图中的sharedInstance类定义了返回自身单例对象的接口。
Singleton的实现
1 |
|
通过GCD来保证线程安全,重写allocWithZone保证不会返回新的实例。
本节工程示例