设计模式 面向对象设计七原则

概论

面向对象设计原则的目的是为了在提高代码可维护性的同时,去提高系统的可复用性。
另一种说法即实现支持可维护性的复用。
一个好的系统设计要具备以下三个性质:
1、可拓展性:容易将新的功能模块加入到系统中。
2、灵活性:代码修改不会波及很多其他的功能模块。
3、可插入性:可以很方便的将一个类抽出,并将另一个有相同接口的类插入进去。

单一职责原则

定义:一个对象应该只包括单个职责,且实现该职责的功能被完整的封装在一个类中,实现高内聚,低耦合。
分析:一个类承担的职责越多,那么他的可复用性就越小,并且会导致类中各职责的耦合度升高,一个职责往往会牵涉到其他的职责,这样当我们想复用其中的某一个职责时,往往会引起其他职责的运作,代码过于僵硬,不符合系统三性质中的灵活性。类的职责主要分为属性职责和方法职责,有时我们只希望a职责执行,而b职责不执行,但由于类中职责太多导致a职责一旦执行会导致b职责的执行,这不是我们所希望看到的,所以将个各职责封装在不同的类中,若一个功能需要ab职责同时负责,那么可以将两职责写在同一个类中。
例子:
在这里插入图片描述
重构以后:
在这里插入图片描述
这样就实现了数据库连接代码和数据库操作代码的复用。

开闭原则

定义:对扩展开放,对修改关闭。
分析:在扩展时能够轻易的扩展功能,而不修改原本已有的代码,这使得系统具有良好的适应性和稳定性。实现开闭原则的关键在于抽象化设计把一个功能模块设计为两层,高层为抽象类定义了抽象方法,底层是具体的实现类,这样需要扩展功能时,只需要新建具体的实体类来实现业务就行了。开闭原则要求”对可变性进行封装“,要求找到系统的可变因素,根据不同的可变因素,为之划分出不同的具体实现类。
实例:
在这里插入图片描述
重构以后:
在这里插入图片描述
这样利用对象的多态性,完成了在既不修改以前的代码的同时,扩展功能只需要继承抽象类,再覆写其中的方法即可。

里氏代换原则

定义:所有引用超类的地方必须能够同名的使用其子类。(实现开闭原则的方式之一)
分析:在软件中如果能使用超类对象,那么必能替换成其子类对象,具体在使用中是在会使用子类对象的地方,使用其超类对象来定义,这样可以接受不同种类的超类的子类对象,符合开闭原则。
使用里氏代换原则需要注意的点:
1、子类的所有方法必须在其超类中声明,不然在替换时无法通过定义的超类对象来调用子类中要实现的方法。
2、尽量把超类设计成接口或者抽象类,这样只需让子类去继承超类,并实现其中的方法,要扩展方法时,只需要在超类中声明方法即可,因为实现是在子类中的,这样可以很方便的扩展系统的功能,而不修改已有原有子类的代码,且在超类中只是多声明了方法,并没有修改已有的代码,这符合开闭原则。
实例:
在这里插入图片描述
在这个实例中我们可以看到在EmailSender类中定义了两个功能一样但参数类型不一样的方法,根据里氏替换原则,若我们想要新增一个客户类的话,则需要再新建一个客户类,但我们知道其实他们发送邮件的行为都是差不多的,且类中的属性和方法基本一致,所以为了减少代码的重复和使系统已扩展,我们可以定义一个抽象类,让客户类派生于此抽象类。由此想再扩展新类型的客户就方便许多了,且不必更改EmailSender中的方法。
在这里插入图片描述

依赖倒转原则

定义:依赖倒转原则是实现面对对象设计目标(实现开闭原则)的主要机制,是系统抽象化的具体实现。“针对接口编程,不要针对实现编程”
分析:代码要依赖于抽象类而不是具体的实现类,也就是说在程序代码传递参数的过程或在聚合组合关系中尽量使用抽象类和接口来定义参数类型,即使用接口和抽象类进行变量的类型声明,参数类型声明,方法返回值的类型声明,以及数据类型的转换等,而不用具体的实现类来做这些事情。而为了确保该原则的正确使用,子类应当只实现抽象类或接口中已经定义的方法,而不要有多余的方法,因为超类对象无法引用自身未定义的方法。

1.类之间的耦合和依赖注入

耦合

1、零耦合关系,两类之间没有任何的交集,即为0耦合。
2、具体耦合关系,两个具体类,一个类对另一个类的实例直接引用而产生的。
3、抽象耦合关系,发生在两个类中至少有一个为抽象类时,依赖倒转原则要求客户端依赖于抽象耦合,由于一个抽象耦合关系总涉及具体累到抽象类的继承,并且保证在任何使用超类的地方可以用子类进行替换,因此里氏替换原则是依赖倒转原则的关键。

依赖注入
我的理解是在一个对象在调用一个方法时,需要注入一个依赖的对象,且在声明这个对象的参数类型时要使用其超类。
1、构造注入
通过构造方法来注入实际依赖的对象
2、设置注入
通过普通方法来注入实际依赖的对象
3、接口注入
通过接口来注入实际依赖的对象

实例
在这里插入图片描述
重构
在这里插入图片描述
借鉴依据刘伟大神的话,开闭原则,里氏替换,依赖倒转,一般是同时出现的,且开闭原则是目标,里氏代换是基础,依赖倒转是手段!!!!

接口隔离原则

定义:接口若太大,则需要分割成更细小的接口,使用该接口的客户端只需知道与之相关的方法即可
分析:我的理解是和类一样要符合单一职责原则,每一个接口承担其单一的职责,子类只需要实现其定义的方法就好,若接口太大,则根据单一职责原则,必须将接口进行划分。在接口划分时,必须依赖于单一职责原则,将一组相关联的操作定义在一个接口当中,且在满足高内聚的情况下,接口中的方法越少越好。

实例

在这里插入图片描述
接口中定义了太多的方法,若要继承该接口,则子类必须覆写其中的全部逻辑,然后客户可能只会使用其中部分方法,有一些方法是内部的不应该让用户看到,所以我们可以将接口按照职责来进行分组,再根据用户的需求单独的为客户定制接口

重构
在这里插入图片描述

合成复用原则

定义:多用聚合和组合关系,少用继承来达到代码复用的目的
分析:继承关系会破坏系统的封装性,超类的改变会导致他一系列子类的改变,灵活性不高,而关联关系则可以将一个类的对象当作一个类对象的一部分,这就相当于在这个类可以使用嵌入其中的类的功能,这也达到了代码的复用,且当对于继承关系来讲类与类之间的耦合度较低,成员对象功能的变化对于新对象的影响不大,且可以根据新对象对功能的需求,有选择性的选择调用的成员对象的操作,合成复用可以在系统运行时动态的进行,新对象可以动态地引用与成员对象类型或其超类相同的其他对象。

实例
在这里插入图片描述
当需要更换数据库种类时,则必须修改DBUtil类或者新建一个DBUtI类让DAO去继承新建的类,毫无疑问这都破坏了开闭原则

重构

在这里插入图片描述
通过此种方式在需要更换数据库时只需要新增DBUtil的子类,然后通过依赖注入的方式来传递对象,这样符合开闭原则,且增强了代码的灵活性。

迪米特法则

定义:不要和陌生人说话,即可以避免增加该类与其他类的耦合度,这样一个类型修改会尽量少的影响其他模块,方便扩展这是对软件实体之间通信的限制,要求限制软件实体之间通信的宽度和深度。
分析:只和"朋友对话"
朋友包括:
1、当前对象本身
2、以参数形式传入当前对象方法中的对象
3、当前对象的成员对象
4、如果当前对象的成员对象是一个集合,那么集合中的类的对象也是朋友
5、当前对象所创建的对象
例如当类A需要调用类C的一个方法时,但类C不是他的朋友,那么类A可以通过依赖类B,而类B与类C是关联关系,这样类A可以通过类B中的方法来调用类C。即迪米特法则不允许a.m1.m2或a.b.m这样的调用方式,在方法调用中只允许一个.。坏处迪米特法则会使得系统中增加大量的小方法,并分散在系统的各个角落,造成对象与对象之间通信效率降低,系统不容易协调。好处就是降低了类之间的耦合度,可以使得各个模块被单独开发和修改。
迪米特法则的主要用途在于控制信息的过载。使用时要注意一下几点
1、在类的划分上尽量创建松耦合度的类,类耦合度越低越利于复用,且便于修改。
2、在类的结构设计商,每一个类应当尽量降低其成员变量和成员函数的访问权限
3、在类的设计商,只要有可能,一个类型应当设计成不变类
4、在对其他类的引用上,一个对象对其他对象的引用应到降低

实例
在这里插入图片描述

重构

在这里插入图片描述

本博客实例资料来自于一下链接
https://blog.csdn.net/lovelion/article/details/7563445

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值