我们在开发中会遇到各种各样的需求,为了应对一些需求,我们将一些解决办法归类,这就是 设计模式。
我们判断是否需要使用设计模式要遵循7个基本原则:
1.单一职责原则
2.接口隔离原则
3.依赖倒转原则
4.里氏替换原则
5.开闭原则
6.迪米特法则
7.合成复用原则
1.单一职责原则
单一职责原则的意思就是一个类只负责一个职责
为什么要这样呢,打个比方,有个类A,其中有两个方法A1、A2,当需求变动的时候需要修改A1,这时修改A类可能会导致A2也受到影响。
列子:
有一个动物类定义了动物的动作,
此时动作是没问题的,但是如果是鱼,就会发现,鱼是不能走路的
这时就要对代码进行修改,如果我们把action方法改为有用,牛又 没办法走路了,这就陷入了很尴尬的境地,此时我们就要使用单一职责原则,首先我们将animal改为一个接口,在其中定义一个动作的方法,而后用两个类去实现
这样就是清晰的看出单一职责的好处,对于鱼的操作都会鱼这个类中去修改,不论怎么变化都不会影响到牛的操作。
2.接口隔离原则
接口隔离原则实际的意为接口分离原则,意思就是将复杂的接口分开,对于要使用接口的类,只暴露他要使用的接口。
我们再看官方的解释:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
我们看例子:
首先我们定义两个接口分别为run和fly
此时在用一个类实现他们两
我们看看调用
Animal实现了两个接口,但是我们只使用一个,所以我们只暴露run方法
接口隔离实际上就是建立在单一职责之上的,但是还是要根据具体情况设计接口中到底需要那些方法
3.依赖倒转原则
在传统的开发中,我们再业务流程中调用方法都是直接调用,比如数据库操作,所以我们一般是先写数据库操作,再写业务流程,而此时如果,将数据库操作交给另外一个同事去写,你就必须等他写完后,你才能继续进行,这明显是很影响效率的,依赖倒转实际上就是面向接口开发,先定义接口,我们不需要关注具体实现,我们只需要调用接口即可,实现由负责数据库的同事进行实现,不影响我们的开发。
举个面向接口的好处:
我们新建一个student类,其中有个read方法,此时我们调用read显示的是读语文书,但是我们要是不想让他读语文书了,我们想让他读数学书,我们唯一的办法就是改代码,改为读数学书。此时面向接口开发的好处就体现出来了。
我们定义一个读书的接口,使用两个类去实现,这是我们想让他读语文书就读语文书,想读数学书就读数学书,如果我们还想让他读别的数,我们只需要再继续实现Read接口就行了
4.里氏替换原则
里氏替换原则意为:子类替换父类后,程序的行为是不受影响的;一个子类的实例应该能够替换任何其超类的实例,通俗点就是,你先创建了一个父类,然后用子类去继承他,最好不要去直接把父类的功能修改了,下面我们来看例子
我新建一个动物类,然后定义一个动作为走路
此时有一个需求需要一个鸭类要会游泳
我重写了action方法,此时鸭子可以游泳了,但是我要是再想让鸭子走路就不行了,
里氏替换法则的意思就是你在继承时,一定要考虑好,最好是在不修改父类的逻辑的情况下进行扩展。
5.开闭 原则
开闭原则就是只允许提供者修改,而使用者不修改,我们直接上列子
我们首先新建一个动物类
之后用一个鸭子类和一个鱼类去继承他并重写他的name方法
然后我们创建一个厨房类 ,如果为1 我们就拿鱼,如果是2我们就拿鸭子
此时我们想再加一个牛的食材,我们则需要修改厨房类,再新增一个牛类,需要改的地方就很多,如果厨房和食材分别由不同的人去维护,需要的代价就更大了,接下来我们再用开闭原则来试试
首先我们将创建一个动物并定义一个接口
之后我们用鱼和鸭子去实现它
此时我们再看厨房类
厨房类只负责调用,后续如果再增加牛食材的话也只需要实现动物接口即可,不需要再到厨房类中修改
6.迪米特法则
迪米特法则意为最少知道原则,最少知道就是除了自己的朋友,尽可能少的让陌生人知道,这里要说一下,什么是朋友
以上三种情况就是Animal的朋友,首先1.成员变量,2返回值,3参数
举一个很简单的例子
我们去外边吃饭,我们只需要点菜,菜是怎么做出来的,我们是不知道的,我们和菜没有直接的关系,我们只需要和厨房有关系即可
7.组合/聚合复用原则
组合/聚合复用原则 其实关键点在于复用,比如子类继承父类的方法,而后你使用子类,如果父类发生变化子类也会受到影响,组合和聚合只是复用的方式
例子:比如人类有男性和女性,黄种人,白种人,黑种人,如果我们使用继承复用的话
等等 这样一套流程下来,生成的类会变得很多,而且随着色种和性别变多,类也会越来越多。
这时我们再使用组合/聚合复用原则 来做
我们用这种 组合/聚合复用原则来做的话,如果要是再增加色种和性别,我们无需修改代码,只要我们增加色种和性别即可。