设计模式之感悟和实践1

背景

设计模式可以说是老生常谈的一个知识点。工作这么多年来也是陆陆续续看过几本书。比如《大话设计模式》、《Head First 设计模式》,这两本书是前期接触比较多,而且质量还是不错的两本书,不过之前看的感觉有点像猪八戒吃人参果——食而不知其味。

很多时候有的人在写代码的过程中对设计模式并不为然。像本人是做APP开发的,APP开发结束后,迭代和新增业务逻辑不是很多的话,确实以前写成啥样其实真的无所谓。直到近来接手了公司一个历史悠久的主项目,由于业务的发展,业务逻辑越来越多,改动越来越大,每次新增业务都举步维艰,让我深刻的体会到了设计模式的优点和威力。

近来正好又重新拾起设计模式在看另外一本书《设计模式之禅》这本书,这本书较之其他两本书感觉比较接地气吧。这次看着很慢,每个模式都在细细的琢磨,再加上之前项目的经验和这次槽糕的老项目,收获比较多,感悟也比较深。

设计原则

要说设计模式,设计原则是必不可缺少的。如果单单去看这几个原则,其实一眼就能看完。原则只是原则,是要尽量保持,而不是必须保持的哦!所以不能一言而论,根据业务和情景懂得变通。

单一原则

应该有且仅有一个原因引起类的变更。

这个原则在使用的过程中要做到适度,如果过度使用的话,可以将一个类中所有的方法都对应做成一个类。
其实在使用过程中说白了就是根据业务或某一方面将功能归类,同一功能的放在一起,声明一个接口。


比如上图,我们根据用户的属性和用的行为,划分为两个接口。

根据以上例子单一原则的有点也是显而易见:类的复杂性降低,可维护性高。

里氏替换原则

只要父类出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用这可能根本就不需要知道是父类还是子类。但是,反过来就不行了。

这个原则用到的其实就是类的继承,在一些情况下继承的优点不言而喻,不过在项目中不要随便使用继承。继承是可以用其他设计模式替换的,比如装饰模式等。
继承具有以下缺点:

  • 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法。这个危害性还是挺大的!
  • 降低了代码耦合性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束
  • 增加了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改时毁灭性的。

如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生"畸形",则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承

依赖倒置原则

高层模块不应该依赖底层模块,两者都应该依赖其抽象(接口或实现类)。一句大白话就是面向接口编程

也就是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的使用,并且业务逻辑很清晰。

总结

其实项目使用过程中,关键一点还是要去发现那块代码会一直变,将经常变换的代码进行设计模式的封装,则以后的代码扩展是非常的方便

我的博客

我的博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 3,734评论 0 14
  • 设计模式基本原则 开放-封闭原则(OCP),是说软件实体(类、模块、函数等等)应该可以拓展,但是不可修改。开-闭原...
    西山薄凉阅读 3,753评论 3 13
  • 只是那一抹笑意的回头 惊鸿一面 而你我相隔 又岂非在人海之间 愿望如山川起伏 期盼如江水东流 回忆 像六月未尽之雨...
    笔墨生锋阅读 251评论 0 2
  • 昨天有几件事让我很开心,77说,你们需要鸡血。我说,我不需要。但说完意识到,自己极力否认的,也许只是我刻意回避的,...
    冠世墨玉yanzi阅读 141评论 2 3
  • 我们很酷, 我们不需要标题! ——漫展管家 伴随着清明小长假的来临,我们筹备已久的蒲公英动漫游戏嘉年华终于要上线啦...
    汪特阅读 393评论 0 1