简而言之,设计模式是为特定场景下的问题而定制的解决方案.
特定场景指问题所在的重复出现的场景.
问题指特定环境下你想达成的目标.
本文主要为创建对象--获取源码
目录
1.原型模式
2.(具体)工厂方法模式
3.抽象工厂模式
3.1类簇
4.生成器模式
5.单例模式
1.原型模式
我认为就是"copy",
也就是说无需自己动手定义一个类来创建对象,直接拿来别的对象copy一下,产生个同一类型的新的对象使用
使用的时候要注意深复制(内存复制),而不是浅复制(指针复制)
*浅复制就是指针复制 出现两个指针 一块地址空间 旧指针和复制指针指向同一块地址空间
如果源地址数据改变 那么两个指针指向的值就会改变
深复制就是指针与空间同时复制 出现两个指针 两块地址空间 互不影响
如果源地址数据变化 复制指针与空间不受影响。
*对于系统的非容器类对象,我们可认为,
如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutbleCopy就是对象复制(深拷贝)
如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
1)对非集合类:
[Object copy] // 浅复制
[Object mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
2)对集合类:
[Object copy] // 浅复制
[Object mutableCopy] //单层深复制
(即仅对对象本身进行深复制,对象元素仍是浅复制(指针拷贝,内存地址不变))
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制
iOS深拷贝与浅拷贝、NSString内存分配
NSString深浅复制的见解
2.(具体)工厂方法模式
numberWithBool方法返回的实际对象类型是NSCFBoolean类型
调用类的工厂方法,接受不同类型的参数,返回该类的对象实例,并决定实例化何种私有具体类
(这也是我们在外部无法直接定义NSCFBoolean类型的原因)
所以叫做"具体工厂方法模式"更加贴切,
各种私有子类重写或重载父类中声明的公有工厂方法,并用这个方法创建自己特色的对象
比如上述工厂方法,创建的NSNumber对象,NSCFBoolean等都是NSNumber的具体工厂子类,子类是具体工厂
3.抽象工厂模式
3.1类簇
提到抽象工厂模式不得不说类簇,类簇是基于抽象工厂模式的思想,也有人说类簇就是一个抽象工厂模式的iOS版本的实现
在上面说过"各种私有子类重写或重载父类中声明的公有工厂方法,并用这个方法创建自己特色的对象",
而这个"声明公有工厂方法"的父类,就是"抽象工厂",再加上"具体工厂"私有子类,这个集合就是"类簇"
它在外层提供了很多方法接口,但是这些方法的实现是由具体的内部类来实现的.当使用NSNumber生成一个对象时,初始化方法会判断哪个“自己内部的类”最适合生成这个对象,然后这个“具体工厂”就会生成这个具体 的类对象返回给你
常见的类簇有NSArray,NSNumber,NSString...
这种由外层类提供统一抽象的接口,然后具体实现让隐藏的,具体的内部类来实现,在设计模式中称为“抽象工厂”模式
扩展:
使用类簇巧妙配置app语言版本:iOS 类簇(Class Cluster)使用心得
类簇
从NSArray看类簇
4.生成器模式
生成器模式就是定义基本属性与组合属性分离,
指导者-生成器-产品
指导者知道生成器应该建造什么产品
生成器知道以什么逻辑建造产品
(构建对象有很多种方式,如果组合对象属性的逻辑全在构建对象的类方法中,那会出现一大片的if-else或者switch-case,结构会很难看)
这种模式最适合用在构建复杂模型的游戏当中
下面就用构建游戏角色属性的方式展示此模式的优点
(建议看源码,一目了然)
(OSZ为oldSixZhu缩写)
基本属性.h:
#import <Foundation/Foundation.h>
@interface OSZCharacter : NSObject
//任何一个角色都有的基本属性
//身高,影响血量
@property (nonatomic, assign) float height;
//体重,影响血量
@property (nonatomic, assign) float weight;
//血量
@property (nonatomic, assign) float blood;
//速度,影响攻击力
@property (nonatomic, assign) float speed;
//力量,影响攻击力
@property (nonatomic, assign) float power;
//攻击力
@property (nonatomic, assign) float attack;
@end
基本属性.m:
#import "OSZCharacter.h"
@implementation OSZCharacter
//初始化下基本属性(统一设置所有模型最低属性值)
-(instancetype)init
{
if (self = [super init])
{
self.height = 0;
self.weight = 0;
self.blood = 0;
self.speed = 0;
self.power = 0;
self.attack = 0;
}
return self;
}
@end
生成器基类.h:
#import <Foundation/Foundation.h>
#import "OSZCharacter.h"
@interface OSZCharacterBuilder : NSObject
@property (nonatomic, strong) OSZCharacter *character;
//character并不知道如何构建一个有意义的属性
//本模型基于character构建有意义的角色属性
- (OSZCharacterBuilder *)buildNewCharacter;
- (OSZCharacterBuilder *)buildHeight:(float)value;
- (OSZCharacterBuilder *)buildWeight:(float)value;
- (OSZCharacterBuilder *)buildSpeed:(float)value;
- (OSZCharacterBuilder *)buildPower:(float)value;
@end
生成器基类.m:
#import "OSZCharacterBuilder.h"
@implementation OSZCharacterBuilder
- (OSZCharacterBuilder *)buildNewCharacter
{
self.character = [[OSZCharacter alloc]init];
return self;
}
- (OSZCharacterBuilder *)buildHeight:(float)value
{
self.character.height = value;
return self;
}
- (OSZCharacterBuilder *)buildWeight:(float)value
{
self.character.weight = value;
return self;
}
- (OSZCharacterBuilder *)buildSpeed:(float)value
{
self.character.speed = value;
return self;
}
- (OSZCharacterBuilder *)buildPower:(float)value
{
self.character.power = value;
return self;
}
@end
实际使用的生成器.h:
#import "OSZCharacterBuilder.h"
@interface OSZStandardCharacterBuilder : OSZCharacterBuilder
//重载下父类的方法,加工真正角色的属性逻辑
//加入身高体重对血量影响的逻辑
//速度力量对攻击力影响的逻辑
- (OSZCharacterBuilder *)buildHeight:(float)value;
- (OSZCharacterBuilder *)buildWeight:(float)value;
- (OSZCharacterBuilder *)buildSpeed:(float)value;
- (OSZCharacterBuilder *)buildPower:(float)value;
@end
实际使用的生成器.m:
#import "OSZStandardCharacterBuilder.h"
@implementation OSZStandardCharacterBuilder
- (OSZCharacterBuilder *)buildHeight:(float)value
{
//1点身高加10点血
self.character.blood += 10 * value;
//处理过后用新值更新目标角色,然后将自身返回
return [super buildHeight:value];
}
- (OSZCharacterBuilder *)buildWeight:(float)value
{
//1点体重加100点血
self.character.blood += 100 * value;
return [super buildWeight:value];
}
- (OSZCharacterBuilder *)buildSpeed:(float)value
{
//1点速度加10点攻击力
self.character.attack += 10 * value;
return [super buildSpeed:value];
}
- (OSZCharacterBuilder *)buildPower:(float)value
{
//1点力量加100点攻击力
self.character.attack += 100 * value;
return [super buildPower:value];
}
@end
指导者.h:
#import <Foundation/Foundation.h>
#import "OSZStandardCharacterBuilder.h"
@interface OSZBuildRole : NSObject
//指导者 指导 生成器 创建返回产品
//把加工过的属性组合起来成为一个具体的角色
//创建玩家
- (OSZCharacter *)createPlayer:(OSZCharacterBuilder *)builder;
//创建boss
- (OSZCharacter *)createBoss:(OSZCharacterBuilder *)builder;
@end
指导者.m:
#import "OSZBuildRole.h"
@implementation OSZBuildRole
- (OSZCharacter *)createPlayer:(OSZCharacterBuilder *)builder
{
//初始化
[builder buildNewCharacter];
//加工
[builder buildHeight:1];
[builder buildWeight:10];
[builder buildSpeed:1];
[builder buildPower:10];
//返回加工过的具体属性模型
return builder.character;
}
- (OSZCharacter *)createBoss:(OSZCharacterBuilder *)builder
{
[builder buildNewCharacter];
[builder buildHeight:10];
[builder buildWeight:100];
[builder buildSpeed:10];
[builder buildPower:100];
return builder.character;
}
@end
c层.m代码:
- (void)viewDidLoad {
[super viewDidLoad];
//生成器
OSZStandardCharacterBuilder *characterBuilder = [[OSZStandardCharacterBuilder alloc]init];
//指导者
OSZBuildRole *role = [[OSZBuildRole alloc]init];
//产品
OSZCharacter *player = [role createPlayer:characterBuilder];
OSZCharacter *boss = [role createBoss:characterBuilder];
NSLog(@"%@\n%@",player,boss);
}
5.单例模式
单例类只会开辟一次内存空间,总是返回自己的同一个实例,它提供了对类的对象所提供的资源的全局访问点.与这类设计相关的设计模式称为单例模式
单例模型OSZSingleton.h:
#import <Foundation/Foundation.h>
#import "singleton.h"
@interface OSZSingleton : NSObject
//测试属性
@property (nonatomic, copy) NSString *name;
//使用宏
singleton_h(OSZSingleton)
//+ (OSZSingleton *)sharedOSZSingleton;
@end
OSZSingleton.m:
#import "OSZSingleton.h"
@implementation OSZSingleton
//使用宏
singleton_m(OSZSingleton)
//static OSZSingleton *_singleton = nil;
//+ (OSZSingleton *)sharedOSZSingleton
//{
// return [[self alloc] init];
//}
//直接重写allocWithZone,防止有人不明白此类为单例类
//alloc是用设为NULL的allocWithZone来调用的
//检查类的唯一实例是否已创建,如果没有,就创建新的实例并返回
//普通实现
//+(instancetype)allocWithZone:(struct _NSZone *)zone
//{
// if (!_singleton)
// {
// _singleton = [super allocWithZone:zone];
// }
// return _singleton;
//}
//防止多线程访问,互斥锁
//+ (instancetype)allocWithZone:(struct _NSZone *)zone {
// @synchronized (self) {
// if (!_singleton) {
// _singleton = [super allocWithZone:zone];
// }
// }
// return _singleton;
//}
//或者GCD一次性执行函数
//+ (instancetype)allocWithZone:(struct _NSZone *)zone {
// static dispatch_once_t onceToken;
// dispatch_once(&onceToken, ^{
// _singleton = [super allocWithZone:zone];
// });
// return _singleton;
//}
// 如果这个单例遵守了NSCopying和NSMutableCopying协议,
// 那么无论是使用copy方法还是mutableCopy方法, 都只会得到同一个实例对象
//- (id)copyWithZone:(NSZone *)zone {
// return _singleton;
//}
//
//- (id)mutableCopyWithZone:(NSZone *)zone {
// return _singleton;
//}
//MRC要重写以下四个方法
//- (instancetype)autorelease
//{
// return _singleton;
//}
//
//- (instancetype)retain
//{
// return _singleton;
//}
//
//- (oneway void)release
//{
//
//}
//
//- (NSUInteger)retainCount
//{
// return 1;
//}
@end
控制器OSZTwoVC.m:
#import "OSZTwoVC.h"
#import "OSZSingleton.h"
@interface OSZTwoVC ()
@end
@implementation OSZTwoVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blueColor];
OSZSingleton *cat1 = [[OSZSingleton alloc]init];
// NSLog(@"%lu",(unsigned long)cat1.retainCount);
cat1.name = @"猫猫";
NSLog(@"%@",cat1.name);
// [cat1 release];
// NSLog(@"%lu",(unsigned long)cat1.retainCount);
OSZSingleton *cat2 = [[OSZSingleton alloc]init];
NSLog(@"%@",cat2.name);
//无论我们创建多少次对象,都是猫猫
}
@end
最后封装的单例宏singleton.h:
#if __has_feature(objc_arc)
#define singleton_h(name) +(instancetype)shared##name;
#define singleton_m(name) static id _instanceType;\
+(instancetype)shared##name\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instanceType = [[self alloc]init];\
});\
return _instanceType;\
}\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instanceType = [super allocWithZone:zone];\
});\
return _instanceType;\
}\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instanceType;\
}
#else
#define singleton_h(name) +(instancetype)shared##name;
#define singleton_m(name) static id _instanceType;\
\
+(instancetype)shared##name\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instanceType = [[self alloc]init];\
});\
return _instanceType;\
}\
\
+(instancetype)allocWithZone:(struct _NSZone *)zone\
{\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
_instanceType = [super allocWithZone:zone];\
});\
return _instanceType;\
}\
\
-(id)copyWithZone:(NSZone *)zone\
{\
return _instanceType;\
}\
\
-(instancetype)autorelease\
{\
return _instanceType;\
}\
\
-(instancetype)retain\
{\
return _instanceType;\
}\
\
-(oneway void)release\
{\
\
}\
\
-(NSUInteger)retainCount\
{\
return 1;\
}
#endif