本文主要内容
一.六大设计原则
二.责任链模式
三.桥接模式
四.适配器模式
五.单例模式
六.命令模式
一.六大设计原则
-
单一职责原则:一个类只负责一件事,例如UIView和CALayer; -
开闭原则:对修改关闭、对扩展开放,例如对类的定义; -
接口隔离原则:使用多个专门的协议,而不是一个庞大臃肿的协议,例如UITableView的Delegate和DataSource; -
依赖倒置原则:抽象不应该依赖于具体实现,具体实现可以依赖于抽象,例如定义数据访问,增删改查的接口; -
里氏替换原则:父类可以被子类无缝替换,且原有功能不受任何影响,例如KVO机制,既使用观察者模式,又遵循里氏替换原则; -
迪米特法则:一个对象应当对其他对象有尽可能少的了解,高内聚、低耦合,例如对象之间尽可能独立。
二.责任链模式
应用程序框架包括一个称为响应者链的架构。该链由一系列响应者事件或操作信息被传递并最终被处理。如果给定的响应者对象不处理特定消息,它会将消息传递给链中的下一个响应者。
引出问题:一个关于需求变更的问题
- 类构成
2.1、责任链使用场景
- 有多个对象可以处理请求,而处理程序只有在运行时才能确定;
- 向一组对象发出请求,而不想显式指定请求的特定处理程序。
2.2 责任链模式的优缺点
优点
- 降低耦合度。它将请求的发送者和接受者解耦;
- 简化了对象。使得对象不需要知道链的结构;
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责;
- 增加新的请求处理类很方便。
缺点
- 不能保证请求一定被接收;
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用;
- 可能不容易观察运行时的特征,有碍于除错。
三.桥接模式
引出问题:一个关于业务解耦的问题
- 类构成
四.适配器模式
一个现有类需要适应变化的问题。
对象适配器(常见)
类构成
- (void)request {
// 适配逻辑
[被适配对象 某方法];
// 适配逻辑
}
对象适配器实现
// 原有类
#import "Target.h"
@implementation Target
- (void)operation {
// 原有的具体业务逻辑
}
@end
// 适配对象类
#import "Target.h"
// 适配对象
@interface CoolTarget: NSObject
// 被适配对象
@property (nonatomic, strong) Target *target;
//对原有方法包装
- (void)request;
@end
#import "CoolTarget.h"
@implementation CoolTarget
- (void)request {
// 额外处理
[self.target operation];
// 额外处理
}
@end
类适配器
五.单例模式
单例模式的实现
+ (id)sharedInstance {
// 静态局部变量
static Juejin *instance = nil;
// 通过dispatch_once方式,确保instance在多线程环境下只被创建一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 创建实例(规避循环调用)
instance = [[super allocWithZone: NULL] init];
});
return instance;
}
// 重写方法【必不可少】:避免不使用sharedInstance创建实例,直接用allocWithZone创建
+ (id)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 重写方法【必不可少】:避免外界使用copyWithZone创建实例
- (id)copyWithZone:(nullable NSZone *)zone {
return self;
}
六.命令模式
- 行为参数化;
- 降低代码重合度。
// Command.h
#import <Foundation/Foundation.h>
@class Command;
typedef void(^CommandCompletionCallBack)(Command* cmd)
@interface Command: NSObject
@property (nonatomic, copy) CommandCompletitonCallBack completion;
// 执行
- (void)execute;
// 取消
- (void)cancel;
// 完成
- (void)done;
@end
// Command.m
#import "CommandManager.h"
@implementation Command
- (void)execute {
// override to subclass
[self done];
}
- (void)cancel {
// 回调置为nil
self.completion = nil;
}
- (void)done {
// 异步回到主队列
dispatch_async(dispatch_get_main_queue(), ^{
if (_completion) {
_completion(self);
}
// 释放,防止循环
self.completion = nil;
[[CommandManager sharedInstance].arrayCommands removeObject: self];
});
}
命令管理者
// CommandManager.h
#import <Foundation/Foundation.h>
#import "Command.h"
@interface CommandManager : NSObject
// 命令管理容器
@porperty (nonatomic, strong) NSMutableArray <Command*> *arrayCommands;
// 命令管理者以单例方式呈现
+ (instancetype)sharedInstance;
// 执行命令
+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion;
// 取消命令
+ (void)cancelCommand:(Command *)cmd;
@end
// CommandManager.m
#import "CommandManager.h"
@implementation CommandManager
// 命令管理者以单例方式呈现
+ (instancetype)sharedInstance {
static CommandManager *instance = nil
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[super allocWithZone: NULL] init];
});
return instance;
}
// 【必不可少】
+ (id)allocWithZone:(Struct _NSZone *)zone {
return [self sharedInstance];
}
// 【必不可少】
- (id)copyWithZone:(nullable NSZone *)zone {
return self;
}
// 初始化方法
- (id)init {
self = [super init];
if(self) {
// 初始化命令容器
_arrayCommands = [NSMutableArray array];
}
return self;
}
// 执行命令
+ (void)executeCommand:(Command *)cmd completion:(CommandCompletionCallBack)completion {
if (cmd) {
// 如果命令正在执行不做处理,否则添加并执行命令
if (![self _isExecutingCommand: cmd]) {
// 添加到到命令容器中
[[[self sharedInstance] arraryCommands] addObject: cmd];
// 设置命令执行完成的回调
cmd.completion = completion;
// 执行命令
[cmd execute];
}
}
}
// 取消命令
+ (void)cancelCommand:(Command *)cmd {
[[[self sharedInstance] arraryCommands] removeObject: cmd];
// 取消执行命令
[cmd cancel];
}
// 判断当前命令是否正在执行
+ (BOOL)_isExecutingCommand:(Command *)cmd {
if (cmd) {
NSArray *cmds = [[self sharedInstance] arrayCommands];
for (command *aCmd in cmds) {
// 当前命令正在执行
if (cmd == aCmd) {
return YES;
}
}
}
return NO;
}
@end
本文总结
问题1:手写单例实现
+ (id)sharedInstance {
// 静态局部变量
static Juejin *instance = nil;
// 通过dispatch_once方式,确保instance在多线程环境下只被创建一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 创建实例(规避循环调用)
instance = [[super allocWithZone: NULL] init];
});
return instance;
}
// 重写方法【必不可少】:避免不使用sharedInstance创建实例,直接用allocWithZone创建
+ (id)allocWithZone:(struct _NSZone *)zone {
return [self sharedInstance];
}
// 重写方法【必不可少】:避免外界使用copyWithZone创建实例
- (id)copyWithZone:(nullable NSZone *)zone {
return self;
}
问题2:了解哪些设计原则,谈谈你的理解
六大设计原则:
-
1.单一职责原则:一个类只负责一件事,例如UIView和CALayer; -
2.开闭原则:对修改关闭、对扩展开放,例如对类的定义; -
3.接口隔离原则:使用多个专门的协议,而不是一个庞大臃肿的协议,例如UITableView的Delegate和DataSource; -
4.依赖倒置原则:抽象不应该依赖于具体实现,具体实现可以依赖于抽象,例如定义数据访问,增删改查的接口; -
5.里氏替换原则:父类可以被子类无缝替换,且原有功能不受任何影响,例如KVO机制,既使用观察者模式,又遵循里氏替换原则; -
6.迪米特法则:一个对象应当对其他对象有尽可能少的了解,高内聚、低耦合,例如对象之间尽可能独立。
问题3:图示简单表示桥接模式的主题结构
定义一个抽象父类A和抽象父类B,把抽象父类B作为抽象父类A的一个成员值,如此就可以衍生出从A1到B1、从A1到B2、从A1到B3的联系。
问题4:UI事件传递机制是怎样实现的?对其中运用到的设计模式是怎样理解?
责任链模式。一个类有一个成员变量(也是当前类的类型)。
有任何问题,欢迎👏各位评论指出!觉得博主写的还不错的麻烦点个赞喽👍