设计模式能够说是老生常谈的一个知识点。工做这么多年来也是陆陆续续看过几本书。好比《大话设计模式》、《Head First 设计模式》,这两本书是前期接触比较多,并且质量仍是不错的两本书,不过以前看的感受有点像猪八戒吃人参果——食而不知其味。编程
不少时候有的人在写代码的过程当中对设计模式并不为然。像本人是作APP开发的,APP开发结束后,迭代和新增业务逻辑不是不少的话,确实之前写成啥样其实真的无所谓。直到近来接手了公司一个历史悠久的主项目,因为业务的发展,业务逻辑愈来愈多,改动愈来愈大,每次新增业务都举步维艰,让我深入的体会到了设计模式的优势和威力。设计模式
近来正好又从新拾起设计模式在看另一本书《设计模式之禅》这本书,这本书较之其余两本书感受比较接地气吧。此次看着很慢,每一个模式都在细细的琢磨,再加上以前项目的经验和此次槽糕的老项目,收获比较多,感悟也比较深。api
要说设计模式,设计原则是必不可缺乏的。若是单单去看这几个原则,其实一眼就能看完。原则只是原则,是要尽可能保持,而不是必须保持的哦!因此不能一言而论,根据业务和情景懂得变通。函数
应该有且仅有一个缘由引发类的变动。组件化
这个原则在使用的过程当中要作到适度,若是过分使用的话,能够将一个类中全部的方法都对应作成一个类。 其实在使用过程当中说白了就是根据业务或某一方面将功能归类,同一功能的放在一块儿,声明一个接口。atom
根据以上例子单一原则的有点也是显而易见:类的复杂性下降,可维护性高。spa
只要父类出现的地方子类就能够出现,并且替换为子类也不会产生任何错误或异常,使用这可能根本就不须要知道是父类仍是子类。可是,反过来就不行了。设计
这个原则用到的其实就是类的继承,在一些状况下继承的优势不言而喻,不过在项目中不要随便使用继承。继承是能够用其余设计模式替换的,好比装饰模式等。 继承具备如下缺点:3d
若是子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生"畸形",则建议断开父子继承关系,采用依赖、汇集、组合等关系代替继承code
高层模块不该该依赖底层模块,二者都应该依赖其抽象(接口或实现类)。一句大白话就是面向接口编程
也就是APP开发过程当中,只要有接口文档,咱们就能够实现APP啦,不须要后台人员api的实现。也能够这么理解。
创建单一接口,不要创建臃肿庞大的接口。
单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽可能少。
例如一个接口的职责可能包含10个方法,这10个方法都放在一个接口中,而且提供给多个模块访问,各个模块按照规定的权限来访问,在系统外经过文档约束“不使用的方法不要访问”,按照单一职位原则是容许的,按照接口隔离原则是不容许的,由于它要求“尽可能使用多个专门的接口”。就是指提供给每一个模块的都应该是单一接口,提供给几个模块就应该有几个接口,而不是建议一个庞大的臃肿的接口。 咱们在使用组件化的过程当中,因为模块间的调用,每一个模块都对外声明一个公共接口,这时候其实就违背了接口隔离原则。好比咱们能够按照同一层级调用声明一个接口,不一样层级的调用声明一个接口。
一个对象应该对其余对象有最少的了解
一个软件实体如类、模块和函数应该对外扩展开放,对修改关闭。即软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该经过扩展来实现变化,而不是经过修改已有的代码来实现变化。
上边啰嗦一下设计模式的原则,其实咱们在项目实践中也就是由于代码违背了其中的原则,而后进行改进,进而演化出设计模式。
因此设计模式都是基于以上原则产生的。
此次咱们介绍的是责任链模式
责任链模式的重点是在“链”上,由一条链去处理类似的请求在链中决定谁来处理这个请求,并返回相应的结果。
经过这个定义不知道你们有没有能想到应用的场景呢?
像在咱们工程中因为业务场景的复杂性,就存在大量的if...else
判断。这样的逻辑致使业务交叉在一块儿,致使每一个业务不清晰,扩展起来不是很方便,而且在iOS中会致使UIViewController
臃肿。
这个时候咱们能够引入责任链模式,调用方不用关心真正的业务处理,只要关心业务分类就行,真正的业务交给一个实体类来处理。
首先咱们看一下责任链模式通用类图
这个看着可能有点不知道因此然,因此咱们来个实例讲解一下,相信看了以后就会恍然大悟。
这是demo全部的类图
ActionClickProtocol
@protocol ActionClickProtocol <NSObject>
- (void)handleClick;
- (void)setNext:(id<ActionClickProtocol>)actionClickHandle;
@end
typedef NS_ENUM(NSUInteger, HandleType) {
CLICK1,
CLICK2,
};
复制代码
ActionClickHandle
@interface ActionClickHandle : NSObject<ActionClickProtocol>
@property (nonatomic,assign)HandleType type;
@property (nonatomic,strong)ActionClickHandle *nextHandle;
@end
@implementation ActionClickHandle
- (void)handleClick {
NSLog(@"共有的处理方法");
}
- (void)setNext:(nonnull id<ActionClickProtocol>)actionClickHandle {
self.nextHandle = actionClickHandle;
}
@end
复制代码
ActionClickEvent1
@interface ActionClickEvent1 : ActionClickHandle
@end
@implementation ActionClickEvent1
-(void)handleClick{
NSLog(@"事件1的处理");
}
@end
复制代码
ActionClickEvent2
@interface ActionClickEvent2 : ActionClickHandle
@end
@implementation ActionClickEvent2
-(void)handleClick{
NSLog(@"事件2的处理");
}
@end
复制代码
MyHandle 这个类是核心对外使用的类
@interface MyHandle : NSObject
- (instancetype)initWithType:(HandleType)type;
- (void)handleClick;
@end
@interface MyHandle()
@property (nonatomic,assign)HandleType type;
@property (nonatomic,strong)ActionClickHandle *nextHandle;
@property (nonatomic,strong)ActionClickEvent1 *event1;
@property (nonatomic,strong)ActionClickEvent2 *event2;
@end
@implementation MyHandle
- (instancetype)initWithType:(HandleType)type{
self = [super init];
if (self) {
_type = type;
_event1 = [[ActionClickEvent1 alloc] init];
_event1.type = CLICK1;
_event2 = [[ActionClickEvent2 alloc] init];
_event2.type = CLICK2;
[_event1 setNextHandle:_event2];
self.nextHandle = _event1;
}
return self;
}
- (void)handleClick{
if (self.nextHandle.type==self.type) {
[self.nextHandle handleClick];
}else{
while (self.nextHandle.type!=self.type) {
self.nextHandle = self.nextHandle.nextHandle;
}
[self.nextHandle handleClick];
}
}
@end
复制代码
使用范例:
MyHandle *myHandle = [[MyHandle alloc] initWithType:CLICK2];
[myHandle handleClick];
复制代码
咱们在使用的过程当中能够面向model开发,将model传入 handleClick
方法中。type则是mode中根据接口数据的返回对应的不一样类型。
这种使用方法彻底能够避免if...else的使用,而且业务逻辑很清晰。
其实项目使用过程当中,关键一点仍是要去发现那块代码会一直变,将常常变换的代码进行设计模式的封装,则之后的代码扩展是很是的方便