SOLID-设计模式六大原则

SOLID-设计模式六大原则

Single Responsibility Principle:单一职责原则

Open Closed Principle:开闭原则

Liskov Substitution Principle:里氏替换原则

Law of Demeter:迪米特法则

Interface Segregation Principle:接口隔离原则

Dependence Inversion Principle:依赖倒置原则

 

Solid(稳定的),虽说大部分的网页和书籍都说原则结合是打造有关稳定、灵活、健壮维护等等的软件,可是我倒是觉得除了上述的目的之外,还有一个重要的目的:相对较少的资源消耗

对于大多数程序员而言,就算不知道设计模式,也可以开发出有关具备需求功能的软件,其缺点在与不好用、不好维护、容易崩溃等等,但是还有一个缺点就是浪费了额外的资源。什么代码冗杂、重用性不高,不就说明资源的浪费吗?

历史老师说:“打仗的根本原因找经济原因,没钱我就扯个理由就打你赚钱,”而类比于软件开发,不就是减少各种消耗吗?

那么我对设计模式的定义是:运用设计模式,完成一个集合稳定、灵活、健壮等等优点,并且消耗相对较少的软件。

 

1.单一职责原则--减少资源相关的浪费

如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因。 --百度百科

通俗来讲就是一个类具有一个种类的功能。

就拿衣食住行进行举例,这是四个种类的功能,但是如果你一开始放在一个类里面,就不符合这个原则,如下面的代码:

class CPeopleAblout

{

    void WearCloth() {}

    void EatSomthing() {}

    void Live() {}

    void Car() {}

};

为什么不符合?从三个维度进行描述:

  1. 专业理论的维度:需要修改WearCloth的相关功能,但是可能导致其他方面的功能也出现了一些不明错误,所以要分成多个功能呢类。
  2. 我的维度:因为浪费资源,开发过程中我只想使用WearCloth相关功能,但是我在实例化对象的时候,还要带着一大堆我用不上的东西,这不是浪费资源吗?
  3. 生活的维度:因为麻烦和浪费。写在一起,意味着当你进行一项功能的时候,必须带着其他的功能,不管你用不用。就比如你去吃饭,去6公里外,我开车子去,这很正常,可是你如果去楼下吃,也需要开车,你难道不觉得很可笑吗?

根据第三点就可以了解到。将所以的功能放在一起,可能满足一些情况,但是可能对于大多数情况而言,是累赘、是麻烦而已。因此,单一遍历原则,很大程度的避免了资源的浪费。

 

2.开放-封闭 + 依赖倒转 --减少修改的浪费

软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。

因此,开放封闭原则主要体现在两个方面:

对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

只有依赖于抽象。实现开放封闭的核心思想就是对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的;而通过面向对象的继承和对多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。

--百度百科

依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

--百度百科

大部分网上,是将两个部分分开,但是我从书籍和网上的知识了解到,可以放在一起进行讨论,因为两种存在共同点:依赖于抽象,而不是具体。

通俗来讲:你可以进行功能上的拓展,但是不能进行功能上的修改(当然,不能修改是相对而言修改更少);并且不是上层依赖于下层,而是上下层都依赖于抽象,通俗来讲就是依赖于接口。

不符合的情况:

 

这种情况不符合的原因:

  1. 专业的维度:当CRiceFactory功能被重写之后,EatThing类需要修改的东西过多;或者是重现添加功能后,需要修改的过多;不是依赖于接口,而是依赖于一个具体的CRiceFactory类了
  2. 我的维度:修改功能或者拓展功能都需要修改较多的地方,对修改的支持是比较好的,但是对于拓展的支持,造成了修改的浪费,你可能需要修改或者添加较多的代码。
  3. 生活的维度:你生活周边有多主食餐馆、专门的面馆、专门的盖浇饭餐馆。你想吃中饭,选择是三种,但是你选择去面馆或者去盖浇饭的时候,都可能存在情况:关门了、售罄了等等情况,这就导致你需要重现启程去另外的餐馆,这就导致了心情、时间的浪费。而去多注释餐馆,东西多,面没了,有饭或者其他的东西,只需要你自己重现选择一个主食。

从生活的维度可以看出:

(1)直接使用时,是可能造成问题,而依赖于抽象是避免这个问题

(2)“多主食餐馆”在代码中起到“抽象的接口”功能,提供一个卖东西的接口,而货物来自于各种工厂(“类”)

(3)用户依赖于抽象和各种类(工厂)依赖于抽象,其实是为了避免可能存在的功能重现和拓展。拓展时,只需要接口去满足,相当于“餐馆”新增加了一个主食种类,而修改时,只是相当于“餐馆”的其中一个主食进行了修改,而对于用户来说,只需要进行一下“选择”,这就减少了对于功能相关的浪费。

修改后:

 

而到这里后,可以进一步分析:“开发-封闭”其实是去其他原则都具有的一个基本原则,简而言之,就是不论你的代码符合那种原则,有运用了那种设计模式,其“对拓展的支持和对功能修改的不支持”是一定需要具备的一种属性,因为反复的修改已有的功能代码,会引发一系列需要修改的地方,这这就造成巨大的修改浪费,还不算同时引发的各种bug等等。

 

3.迪米特法则 + 接口隔离原则

迪米特法则:资源消耗和低耦合度的权衡

接口隔离原则:低耦合度和资源消耗的权衡

 

迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle)

一个软件实体应当尽可能少的与其他实体发生相互作用。

每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。 --百度百科

 

客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。

“不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。”

--百度百科

从说明中分析可知:

迪米特法则分为依赖部分和被依赖部分:

依赖部分:只依赖需要依赖的类。

被依赖部分:只提供需要提供的接口。

接口隔离原则:

接口部分:细化、分类接口,让服务于不同功能的接口进行分离,放在一起,不被使用的接口就是浪费

类使用部分:值暴露接口需要的函数,即类根据接口定制public函数,其他不被使用的函数、变量等等直接private或者protected。

从生活的维度举例:

1.迪米特法则

就像搭公交车的时候,你从后门上车,会将公交卡或者手机,一个人接着一个人的传递,帮你付钱。你不会同时交给两个对象。

 

对于A来说,目的是让D刷自己的卡。而A其实可以直接自己过去,但是很难,就相当于“跨项目”那么就需要第三方进行通讯,寻找到对象B,而在使用的时候:

A是依赖者,我只需要依赖B,那么就只依赖于B,而不寻找其他的路径了。

B是被依赖者,我只需要提供两个接口,拿卡、出卡,其他的不需要

优点:是耦合度低,容易重用,可以说是B、C这两个对象是可以方便替换的。

缺点:当第三方过多时,会造成系统的复杂性,增加消耗。就相当于图中C,D直接还存在EFG...可能你都下车了,卡还没有传回来等等问题

2.接口隔离原则

类似于“单一职责原则”,对于一个“interface”来说,他负责的功能是一类的。而对于继承于他的类来说,类所暴露的接口是根据接口所定制的。

简单举例:

单一职责:对于手机的一个app的功能,单一的功能,用起来舒服

接口隔离:对于现在的手机,一般只有三个按键,大小音量和电源,因为大部分通过触屏,而四个可以理解为控制手机的接口,而在老人机上有一个键盘,也是一种接口,这就是接口隔离,智能手机不需要键盘,所以将其分类出去,用在需要加键盘的老人机上。

优点:低耦合度,容易重用。

缺点:太过于细分的接口容易导致系统负责,增大消耗

 

4.里氏替换

里氏替换原则(Liskov Substitution principle)是对子类型的特别定义。

里氏替换原则的内容可以描述为: “派生类(子类)对象可以在程式中代替其基类(超类)对象。”  --百度百科

另外一种说法就是,子类可以完全替换掉父类,并且不造成任何的问题。分析而知这是对“继承和派生”的规范,让你正确的使用派生,并且是对“开发-封闭”中拓展开放的补充。

从生活的维度举例:

将继承和派生看作是换房子,当然是想要越大越好的房子,但是老房子里面的A,B,C三个物品你一定不会舍弃,在A,B...房子中进行选择,

 

A,B是并列的可选择房子,相当于从现在的房子进行派生,他们需要具备全部的ABC,而不能完全具备的就不能派生出来,就不会被你选择。

由此可分析继承和派生的一些重要点:

  1. 同一个父类派生出来的子类,必须具备父类所需要的ABC...特性
  2. 父类对于所有子类来说,是一个共同点集合之地
  3. 子类可替代父类,就相当于选择了一个新房子,东西都搬过去了

在图中NewHouseB就是不正确的继承,因为他不能继承B这个特点,你可以认为他是宠物,而Bhouse所在的小区不让样宠物等等。

因此,里氏替换原则使用来保证你的继承派生使用正确,减少潜在的bug问题和消耗。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值