IOS设计模式

一、创建型模式

1.单例模式

static CSStudent *_student;
@implementation CSStudent
+ (CSStudent*)sharedCSStudent{
//    方法一
 staticdispatch_once_tonetoken;
    dispatch_once(&onetoken, ^{
_student= [[selfalloc]init];
    });
//    方法二
 @synchronized (self) {
 if(!_student){
            _student= [[CSStudentalloc]init];
        }
    }
 return _student;
}

2.三种工厂模式

2.1 简单工厂模式
  • 工厂角色:接受客户端的请求,通过请求负责创建相应的产品对象。
  • 抽象产品角色:是工厂模式所创建对象的父类或是共同拥有的接口。
  • 具体产品对象:工厂模式所创建的对象都是这个角色的实例。

工厂角色

SLFactory.h文件

#import 
#import "SLOperation.h"

typedef NS_ENUM(NSInteger,SLFactoryProductType){
    SLFactoryProductTypeMantou,
    SLFactoryProductTypeYoutiao,
};

NS_ASSUME_NONNULL_BEGIN

@interface SLFactory : NSObject
//工厂(Factory)角色:接受客户端的请求,通过请求负责创建相应的产品对象。
+ (SLOperation *)operationBreakfast:(SLFactoryProductType)breakfastType;
@end

NS_ASSUME_NONNULL_END
SLFactory.m 文件

#import "SLFactory.h"
#import "SFOperationMantou.h"
#import "SFOperationYoutiao.h"

@implementation SLFactory
+ (SLOperation*)operationBreakfast:(SLFactoryProductType)breakfastType{
    SLOperation *operation;
    switch (breakfastType) {
        case SLFactoryProductTypeMantou:
            operation = [[SFOperationMantou alloc]init];
            break;
        case SLFactoryProductTypeYoutiao:
            operation = [[SFOperationYoutiao alloc]init];
            break;
        default:
            return nil;
            break;
    }
    return operation;
}
@end

抽象产品角色:通过子类来获取具体的角色

SLOperation.h 文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface SLOperation : NSObject

@property (nonatomic, copy, readonly)NSString *product;

- (void)productBreakfast;

@end

NS_ASSUME_NONNULL_END
SLOperation.m 文件

#import "SLOperation.h"

@implementation SLOperation
- (void)productBreakfast{}
@end

具体产品角色

SFOperationMantou.h 文件

#import "SLOperation.h"

NS_ASSUME_NONNULL_BEGIN

@interface SFOperationMantou : SLOperation
- (void)productBreakfast;
@end

NS_ASSUME_NONNULL_END
SFOperationMantou.m 文件

#import "SFOperationMantou.h"

@implementation SFOperationMantou

// 注意这里:@synthesize 重写setter,getter方法
@synthesize product = _product;

- (void)productBreakfast{
    _product = @"馒头";
}
@end
2.2 工厂方法模式

工厂方法使用OOP的多态性,将工厂和产品都抽象出一个基类,在基类定义统一的接口,然后在具体的工厂中创建具体的产品。

  • 抽象工厂角色:与应用程序无关,任何在模式中创建对象的工厂必须实现这个接口。
  • 具体工厂角色:实现了抽象工厂接口的具体类,含有与引用密切相关的逻辑,并且受到应用程序的调用以创建产品对象
  • 抽象产品角色:工厂方法所创建产品对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
  • 具体产品角色:这个角色实现了抽象产品角色所声明的接口。工厂方法所创建的每个具体产品对象都是某个具体产品角色的实例。

抽象工厂角色

SLFactory2.h 文件

#import 
#import "SLOperation2.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLFactory2 : NSObject
+ (SLOperation2 *)createOperation;
@end

NS_ASSUME_NONNULL_END
SLFactory2.m 文件

#import "SLFactory2.h"

@implementation SLFactory2
+ (SLOperation2 *)createOperation{
    SLOperation2 *operation = [[SLOperation2 alloc]init];
    return operation;
}
@end

抽象产品角色

SLOperation2.h 文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface SLOperation2 : NSObject
@property (nonatomic, copy, readonly)NSString *product;
- (void)productBreakfast;
@end

NS_ASSUME_NONNULL_END
SLOperation2.m 文件

#import "SLOperation2.h"

@implementation SLOperation2
- (void)productBreakfast{}
@end

具体工厂角色

SLFactoryMantou2.h  文件

#import "SLFactory2.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLFactoryMantou2 : SLFactory2

@end

NS_ASSUME_NONNULL_END
SLFactoryMantou2.m  文件

#import "SLFactoryMantou2.h"
#import "SLOperationMantou2.h"

@implementation SLFactoryMantou2
+ (SLOperation2 *)createOperation{
    return [[SLOperationMantou2 alloc]init];
}
@end

具体产品角色

SLOperationMantou2.h  文件

#import "SLOperation2.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLOperationMantou2 : SLOperation2
- (void)productBreakfast;
@end

NS_ASSUME_NONNULL_END
SLOperationMantou2.m  文件

#import "SLOperationMantou2.h"

@implementation SLOperationMantou2
@synthesize product = _product;
- (void)productBreakfast{
    _product = @"馒头";
}
@end
2.3 抽象工厂设计模式

所谓抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。

  • 抽象工厂角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
  • 具体工厂角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
  • 抽象产品角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或他们共同拥有的接口。
  • 具体产品角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这个客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。

抽象工厂角色

SLFactory3.h 文件

#import 
#import "SLOperation3.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLFactory3 : NSObject
typedef NS_ENUM(NSInteger,SLFactory3ProductType){
    SLFactory3ProductTypeMantou,
    SLFactory3ProductTypeYoutiao,
};
+ (instancetype)factoryWithType:(SLFactory3ProductType)type;
- (SLOperation3*)createProduct;
@end

NS_ASSUME_NONNULL_END
SLFactory3.m 文件

#import "SLFactory3.h"
#import "SLFactoryMantou.h"
#import "SLFactoryYoutiao.h"

@implementation SLFactory3
+ (instancetype)factoryWithType:(SLFactory3ProductType)type{
    SLFactory3 *factory;
    switch (type) {
        case SLFactory3ProductTypeMantou:
            factory = [[SLFactoryMantou alloc]init];
            break;
        case SLFactory3ProductTypeYoutiao:
            factory = [[SLFactoryYoutiao alloc]init];
            break;
        default:
            break;
    }
    return factory;
}
- (SLOperation3*)createProduct{
    return nil;
}
@end

抽象产品角色

SLOperation3.h 文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface SLOperation3 : NSObject
@property (nonatomic, copy, readonly)NSString *product;
- (void)productBreakfast;
@end

NS_ASSUME_NONNULL_END
SLOperation3.m 文件

#import "SLOperation3.h"

@implementation SLOperation3
- (void)productBreakfast{}
@end

具体工厂角色

SLFactoryMantou.h 文件

#import "SLFactory3.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLFactoryMantou : SLFactory3

@end

NS_ASSUME_NONNULL_END
SLFactoryMantou.m 文件

#import "SLFactoryMantou.h"
#import "SLOperationMantou3.h"

@implementation SLFactoryMantou
- (SLOperation3 *)createProduct{
    return [[SLOperationMantou3 alloc] init];
}
@end

具体产品角色

SLOperationMantou3.h 文件

#import "SLOperation3.h"

NS_ASSUME_NONNULL_BEGIN

@interface SLOperationMantou3 : SLOperation3

@end

NS_ASSUME_NONNULL_END
SLOperationMantou3.m 文件

#import "SLOperationMantou3.h"

@implementation SLOperationMantou3
@synthesize product = _product;
- (void)productBreakfast{
    _product = @"馒头";
}
@end

二、结构型模式

1.代理模式

用来处理事件的监听和参数传递。@required 必须实现这个协议方法;@optional可选实现。最好先判断方法是否实现:if(self.delegate && [self.delegate respondsToSelector:@selector(XXX)]){

delegate和block、Notification对比优缺点:delegate和block是一对一通信、block比delegate更加简洁清晰,但是如果通信事件较多时delegate运行成本较低且不易造成循环引用;通知合适一对多通信,注册通知要注意在合适的时间移除。

DelegateObj.h 文件

#import 

@protocol DelegateObjDelegate 

@required //必须实现
- (void)delegateRequiredFunc:(id)obj;

@optional //可选实现
- (void)delegateOptionalFunc:(id)obj;

@end

NS_ASSUME_NONNULL_BEGIN

@interface DelegateObj : NSObject

@property (nonatomic, weak) id delegate;
- (void)func;

@end

NS_ASSUME_NONNULL_END
DelegateObj.m 文件

#import "DelegateObj.h"

@implementation DelegateObj
- (void)func{
    if(self.delegate && [self.delegate respondsToSelector:@selector(delegateRequiredFunc:)]){
        [self.delegate delegateRequiredFunc:nil];
    }
    if(self.delegate && [self.delegate respondsToSelector:@selector(delegateOptionalFunc:)]){
        [self.delegate delegateOptionalFunc:nil];
    }
}
@end

2.类簇

Foundation框架中广泛使用的设计模式,类簇在公共抽象超类下对多个私有的具体子类进行分组。以这种方式对类进行分组简化了面向对象框架的公共可见体系结构,而不会降低其功能丰富度。类簇是基于抽象工厂设计模式的

3.装饰模式

动用组合,少用继承
装饰者模式,是面向对象编程中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,装饰者模式相比成子类更为灵活,这样可以给某个对象而不是类添加一些功能。

咖啡饮料的价格 = 咖啡本身的价格 + 各种调料的价格
Espresso Macchiato(浓缩玛奇朵)的价格 = Espresso(浓缩咖啡) 的价格 +Milk(牛奶)的价格 + Mocha(摩卡)的价格。


咖啡本身的 Beverage 协议

#import 

NS_ASSUME_NONNULL_BEGIN

@protocol Beverage 
@optional
- (NSString *)getName;
- (double)cost;
@end

NS_ASSUME_NONNULL_END

Espresso

Espresso.h 文件

#import 
#import "Beverage.h"

NS_ASSUME_NONNULL_BEGIN

@interface Espresso : NSObject

@end

NS_ASSUME_NONNULL_END
Espresso.m 文件

#import "Espresso.h"

@implementation Espresso{
    NSString *_name;
}

- (instancetype)init{
    if (self = [super init]) {
        _name = @"Espresso";
    }
    return self;
}

-(NSString *)getName{
    return _name;
}

-(double)cost{
    return 1.99;
}

@end

各种调料的 CondimentDecorator 协议

#import 
#import "Beverage.h"

NS_ASSUME_NONNULL_BEGIN

@protocol CondimentDecorator 

@end

NS_ASSUME_NONNULL_END

Milk(牛奶)

Milk.h 文件

#import 
#import "CondimentDecorator.h"

NS_ASSUME_NONNULL_BEGIN

@interface Milk : NSObject
@property (strong, nonatomic)id beverage;
- (instancetype)initWithBeverage:(id) beverage;
@end

NS_ASSUME_NONNULL_END
Milk.m 文件

#import "Milk.h"

@implementation Milk{
    NSString *_name;
}

- (instancetype)initWithBeverage:(id)beverage{
    if (self = [super init]) {
        _name = @"Milk";
        self.beverage = beverage;
    }
    return self;
}

- (NSString *)getName{
    return [NSString stringWithFormat:@"%@ + %@",[self.beverage getName],_name];
}

- (double)cost{
    return .30 + [self.beverage cost];
}

@end

Mocha(摩卡)

Mocha.h 文件

#import 
#import "CondimentDecorator.h"

NS_ASSUME_NONNULL_BEGIN

@interface Mocha : NSObject
@property (strong, nonatomic) id beverage;
- (instancetype)initWithBeverage:(id) beverage;

@end

NS_ASSUME_NONNULL_END
Mocha.m 文件

#import "Mocha.h"

@implementation Mocha{
    NSString *_name;
}

- (instancetype)initWithBeverage:(id)beverage{
    if (self = [super init]) {
        self.beverage = beverage;
        _name = @"Mocha";
    }
    return self;
}

- (NSString *)getName{
    return [NSString stringWithFormat:@"%@ + %@",[self.beverage getName],_name];
}

- (double)cost{
    return .20 + [self.beverage cost];
}

@end

4.享元模式

享元模式主要用于减少同一类对象的大量创建,以减少内存占用,提高项目流畅度。ios中的UITableViewCell,及线程池 就用了享元模式。
两个关键:1.可共享的享元对象 2.享元池
工厂方法是这一角色的候选对象

FlowerFactory.h  文件

#import 
#import "Flower.h"

NS_ASSUME_NONNULL_BEGIN

typedef enum{
    kRedFlower,     //0
    kBlueFlower,    //1
    kYellowFlower,  //2
    kTotalNumberFlower  //用于计数
}FlowerType;

@interface FlowerFactory : NSObject
@property (nonatomic, strong) NSMutableDictionary *flowerPools;//缓存池,存放享元对象
- (Flower*)flowerViewWithType:(FlowerType)type;
- (void)detailsType;
@end

NS_ASSUME_NONNULL_END

FlowerFactory.m  文件

#import "FlowerFactory.h"

@implementation FlowerFactory
- (Flower *)flowerViewWithType:(FlowerType)type{
    if(self.flowerPools == nil){
        self.flowerPools = [[NSMutableDictionary alloc]initWithCapacity:kTotalNumberFlower];
    }
    Flower *flower = [self.flowerPools objectForKey:[NSNumber numberWithInteger:type]];
    if(flower == nil){
        flower = [[Flower alloc]init];
        switch (type) {
            case kRedFlower:
                flower.flowerColor = @"红色的花";
                flower.flowerName = @"红玫瑰";
                break;
            case kBlueFlower:
                flower.flowerColor = @"蓝色的花";
                flower.flowerName = @"蓝玫瑰";
                break;
            case kYellowFlower:
                flower.flowerColor = @"黄色的花";
                flower.flowerName = @"野菊花";
                break;
            default:
                break;
        }
        [self.flowerPools setObject:flower forKey:[NSNumber numberWithInt:type]];
    }
    return flower;
}

- (void)detailsType{
    NSArray *array = [self.flowerPools allKeys];
    for (NSNumber *key in array) {
        NSLog(@"di zhi = %@, key = %@",self.flowerPools[key],key);
    }
}
@end
Flower.h   文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface Flower : NSObject
@property (nonatomic, copy) NSString *flowerColor;
@property (nonatomic, copy) NSString *flowerName;
@end

NS_ASSUME_NONNULL_END

使用方法

#import "ShareEle/Flower.h"
#import "ShareEle/FlowerFactory.h"


FlowerFactory *factory = [[FlowerFactory alloc]init];
    
  NSMutableArray *arrayFlowers = [[NSMutableArray alloc]init];
    for (int i = 0; i < 5000*100; ++i) {
        FlowerType flowerType = arc4random_uniform(kTotalNumberFlower);
        Flower *flower = [factory flowerViewWithType:flowerType];
//        Flower *flower = [[Flower alloc] init];
        [arrayFlowers addObject:flower];
        [factory detailsType];
     }

三、行为型模式

1.观察者模式

观察者模式 完美的将观察者和被观察者的对象分离开


普通属性

@property (nonatomic, assign) NSInteger num;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self addObserver:self forKeyPath:@"num" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.num++;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keyPath isEqualToString:@"num"]){
        NSLog(@"%@-----%@",change[@"old"],change[@"new"]);
    }
}

观察的是数组集合类数组元素和个数的变化

@property (nonatomic, strong) NSMutableArray *numAry;

- (void)viewDidLoad {
    [super viewDidLoad];
   self.numAry = [NSMutableArray array];
    [self.numAry addObject:@(0)];
    [self addObserver:self forKeyPath:@"numAry" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}

static int indexNum = 1;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self mutableArrayValueForKey:@"numAry"][0] = @(indexNum);
    indexNum++;
    NSLog(@"添加后数组:%@",self.numAry);
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keyPath isEqualToString:@"numAry"]){
        NSLog(@"%@-----%@",change[@"old"],change[@"new"]);
    }
}

观察的是数组中某一个元素的属性的变化

Person.h  文件

#import 

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject
@property (nonatomic, assign) int num;
@end

NS_ASSUME_NONNULL_END


调用文件
#import "Person.h"

@property (nonatomic, strong) NSMutableArray *numAry;

- (void)viewDidLoad {
    [super viewDidLoad];

    self.numAry = [NSMutableArray array];
    for (int i = 0; i < 10; i++) {
        Person *person = [[Person alloc]init];
        person.num = i;
        [self.numAry addObject:person];
    }
    NSIndexSet *indexSet = [[NSIndexSet alloc]initWithIndex:2];
    [self.numAry addObserver:self toObjectsAtIndexes:indexSet forKeyPath:@"num" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}

static int indexNum = 1;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    ((Person *)self.numAry[2]).num = indexNum;
    indexNum++;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keyPath isEqualToString:@"num"]){
        NSLog(@"监听变化:%@---%@",change[@"old"],change[@"new"]);
    }
}

2.命令模式

命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却任可以对他执行任何已有的操作。通过把请求封装成对象,客户端可以把它参数化并置入队列或日志中,也能够支持可撤销操作。命令对象将一个或多个动作绑定到特定的接收器。命令模式消除了作为对象的动作和执行它的接收器之间的绑定。

你可能感兴趣的:(IOS设计模式)