设计模式

  • 前言
  • 一、单一职责原则
    • 1、定义
    • 2、 问题由来
    • 3、单一职责优点:
  • 二、里式替换原则
    • 1.定义:
    • 2.含义:
    • 3.优缺点:
    • 4.注意事项
  • 三、依赖倒置原则
    • 1.定义
    • 2.作用
    • 3.实现方法
    • 核心思想
  • 四、接口隔离原则
    • 1.定义
    • 2.实现方法:
    • 3.接口隔离原则和单一职责的区别:
    • 4.接口隔离原则的优点
  • 五、迪米特法则
    • 1.定义
    • 2.实现方法
    • 3.优点
    • 4.缺点:
  • 六、开闭原则
    • 1.定义
    • 2.作用
  • 总结

前言

这段时间学习了关于JAVA设计模式的课程,看完视频后感觉虽然都有点印象,但是掌握的不深,所以整理一下前面的笔记和上网找了一下相关资料
设计模式:是一套被反复使用、多数人知晓的、经过分类编目的、 代码设计经验的总结。
设计模式用处:它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。
设计模式目的:提高代码的可重用性、代码的可读性和代码的可靠性。


一、单一职责原则

1、定义

不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。

2、 问题由来

类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。遵循单一职责原则。分别建立两个类T1、T2,使T1完成职责P1功能,T2完成职责P2功能。这样,当修改类T1时,不会使职责P2发生故障风险;同理,当修改T2时,也不会使职责P1发生故障风险。

3、单一职责优点:

降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
提高类的可读性。复杂性降低,自然其可读性会提高。 提高系统的可维护性。可读性提高,那自然更容易维护了。
变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响
例子:打电话:
下面展示一些 内联代码片

public interface IPhone{
//拨通电话public void dial(String phoneNumber); //通话public void chat(Object o);//通话完毕,挂断电话public void hangup(); }

打电话分成了:1.协议管理,2、数据传送。

//public interface IPhone{}
public interface IConnectionManager extends IPhone{ //拨通电话public void dial(String phoneNumber); //通话完毕,挂断电话public void hangup(); }public interface IDataTransfer extends IPhone{//通话 public void chat(IConnectionManager con);}

二、里式替换原则

1.定义:

(1).如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
(2).所有引用基类的地方必须能透明地使用其子类的对象。

2.含义:

1.子类必须完全实现父类的方法。
2. 子类中可以增加自己特有的方法。
3. 当子类覆盖或实现父类的方法时,方法的输入参数(方法的形参)要比父类方法的输入参数更宽松。
4. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

3.优缺点:

优点:

  1. 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
  2. 提高代码的重用性;
  3. 提高代码的可扩展性,子类可形似于父类,但异于父类,保留了自己独特的个性;其实很多开源框架的扩展都 是通过继承父类实现的。
  4. .提供产品或者项目的开放性。

缺点:

  1. 继承是侵入性的,只要继承就必须拥有父类的所有方法和属性;
  2. 降低了代码的灵活性。子类必须拥有父类的属性和方法,让子类中多了约束
  3. 增加了耦合,当父类的常量、变量或者方法被修改了,需要考虑子类的修改,所以一旦父类有了变动,很可能 会造成非常糟糕的结果,要重构大量的代码。

4.注意事项

当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。
继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。
例子:
这是个简单的减法运算

class A{public int func1(int a, int b){return a-b;}
}public class Client{public static void main(String[] args){A a = new A();System.out.println("100-50="+a.func1(100, 50));System.out.println("100-80="+a.func1(100, 80));}
}

需要增加一个新的功能:完成两数相加,然后再与100求和,由类B来负责。即类B需要完成两个功能

class B extends A{public int func1(int a, int b){return a+b;}public int func2(int a, int b){return func1(a,b)+100;}
}public class Client{public static void main(String[] args){B b = new B();System.out.println("100-50="+b.func1(100, 50));System.out.println("100-80="+b.func1(100, 80));System.out.println("100+20+100="+b.func2(100, 20));}
}

类B在给方法起名时无意中重写了父类的方法,造成所有运行相减功能的代码全部调用了类B重写后的方法,造成原本运行正常的功能出现了错误。

三、依赖倒置原则

1.定义

高层模块不应该依赖低层模块,两者都应该依赖其抽象; 抽象不应该依赖细节, 细节应该依赖抽象。

个人理解:
类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
解决:
将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。

2.作用

依赖倒置原则可以降低类间的耦合性。
依赖倒置原则可以提高系统的稳定性。
依赖倒置原则可以减少并行开发引起的风险。 依赖倒置原则可以提高代码的可读性和可维护性。

3.实现方法

  1. 每个类尽量提供接口或抽象类,或者两者都具备。
  2. 变量的声明类型尽量是接口或者是抽象类。
  3. 任何类都不应该从具体类派生。
  4. 尽量不要覆写基类的方法
  5. 使用继承时结合里氏替换原则。

核心思想

面向接口编程,而不是面向实现
例子:母亲给孩子讲故事

class Book{public String getContent(){return "很久很久以前有一个阿拉伯的故事……";}
}class Mother{public void narrate(Book book){System.out.println("妈妈开始讲故事");System.out.println(book.getContent());}
}public class Client{public static void main(String[] args){Mother mother = new Mother();mother.narrate(new Book());}
}


这时候如果不想读书,而是读报纸的话

class Newspaper{public String getContent(){return "林书豪38+7领导尼克斯击败湖人……";}
}

必须要修改Mother才能读。

class Mother{public void narrate(Book book){System.out.println("妈妈开始讲故事");System.out.println(Newspaper.getContent());}
}

原因就是Mother与Book之间的耦合性太高了,必须降低他们之间的耦合度才行。
引入一个抽象的接口IReader

interface IReader{public String getContent();
}

Mother类与接口IReader发生依赖关系,而Book和Newspaper都属于读物的范畴,他们各自都去实现IReader接口

class Newspaper implements IReader {public String getContent(){return "林书豪17+9助尼克斯击败老鹰……";}
}
class Book implements IReader{public String getContent(){return "很久很久以前有一个阿拉伯的故事……";}
}class Mother{public void narrate(IReader reader){System.out.println("妈妈开始讲故事");System.out.println(reader.getContent());}
}public class Client{public static void main(String[] args){Mother mother = new Mother();mother.narrate(new Book());mother.narrate(new Newspaper());}
}

四、接口隔离原则

1.定义

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

2.实现方法:

(1)接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
(2)为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
(3)了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同深入了解业 务逻辑。
(4)提高内聚,减少对外交互。
(5)使接口用最少的方法去完成最多的事情。

3.接口隔离原则和单一职责的区别:

(1).单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
(2).单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象 和程序整体框架的构建。

4.接口隔离原则的优点

  1. 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
  2. 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
  3. 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使 设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
  4. 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
  5. 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫 设计冗余的代码。

例子:对美女的定义
建立一个接口:美女

实现美女接口

给个名字

提要求:

展示美女


这就把美女的东西展示出来了
但是要知道,人类的审美时时刻刻在变化
这时候就发现我们的接口太死了,有一些有缺点但是也好看的
这时候就要衍生新的接口了

对于这个美女,虽然没有气质,但是外貌和脸身材都非常棒,所以也是个美女
实现他们

五、迪米特法则

1.定义

又叫作最少知识原则,它要求一个对象应该对其他对象有最少的了解。通俗的说,一个类应该对自己需要耦合或调用的 类知道的最少,被耦合或调用的类的内部是如何复杂都与我无关,我就知道你提供的public方法就好。

2.实现方法

  1. 在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
  2. 在类的结构设计上,尽量降低类成员的访问权限。 3. 在类的设计上,优先考虑将一个类设置成不变类。
  3. 在对其他类的引用上,将引用其他对象的次数降到最低。
  4. 不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
  5. 谨慎使用序列化(Serializable)功能。

3.优点

(1)降低了类之间的耦合度,提高了模块的相对独立性。
(2)由于亲合度降低,从而提高了类的可复用率和系统的扩展性。

4.缺点:

过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低。

六、开闭原则

1.定义

一个软件实体应 该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。

2.作用

  1. 对软件测试的影响 软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
  2. 可以提高代码的可复用性粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
  3. 可以提高软件的可维护性遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
    3.认识:
    遵循设计模式前面5大原则,以及使用23种设计模式的目的就是遵循开闭原则。

总结

1.单一职责原则告诉我们实现类要职责单一;
2.里氏替换原则告诉我们不要破坏继承体系;
3.依赖倒置原则告诉我们要面向接口编程;
4.接口隔离原则告诉我们在设计接口的时候要精简单一;
5.迪米特法则告诉我们要降低耦合。
开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。
对这六个原则的遵守并不是是和否的问题,而是多和少的问题,也就是说,我们一般不会说有没有遵守,而是说遵守程度的多少。任何事都是过犹不及,设计模式的六个设计原则也是一样,制定这六个原则的目的并不是要我们刻板的遵守他们,而需要根据实际情况灵活运用。

上述部分代码参考自:链接: link.

JAVA关于设计模式六大设计原则相关推荐

  1. 设计模式-六大设计原则(附加实际开发建议以及计算器例子)

    使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.设计模式使代码编制真正工程化,是软件工程的基石脉络,如同大厦的结构一样. 文章结构: 1.单一职责原则(SRP): 2.里氏替换原 ...

  2. 设计模式—六大设计原则

    本文开始对<设计模式之禅>进行学习总结,首先是六大设计原则. 单一职责原则 单一职责原则(Single Responsibility Principle)简称SRP,这个原则存在的争议之处 ...

  3. Java设计模式六大设计原则

    从今年的七月份开始学习设计模式到9月底,设计模式全部学完了,在学习期间,总共过了两篇:第一篇看完设计模式后,感觉只是脑子里面有印象但无法言语.于是决定在看一篇,到9月份第二篇设计模式总于看完了,这一篇 ...

  4. UML类图、JAVA DesignMode 设计模式、设计原则

    全文2.6W余字,读完需要20分钟,介绍23种设计模式,每个模式都有案例与真实使用场景,能够帮助初学者快速了解设计模式,建立起对代码中设计模式的初步理解,要明确:设计模式只是帮助我们更好的设计代码架构 ...

  5. java设计模式-六大设计原则

     1. .单一职责            一个类只负责一项职责.      2. 里氏替换原则     子类可以扩展父类的功能,但不能改变父类原有的功能.它包含以下4层含义:     子类可以实现父类 ...

  6. 设计模式六大设计原则 详细整理版

    一.单一职责原则 定义: 一个接口,类或者方法只有一个原因引起变化.即只有一个职责. 解读: 职能多样是一个诱惑,一个方法如果能根据入参(可变参数等)或其他判断条件实现不同或多种功能,看起来很强大而且 ...

  7. 设计模式 - 六大设计原则之SRP(单一职责)

    文章目录 概述 Case Bad Impl Better Impl 1. 定义接口 2. 职责分离-多种实现类 3. 单元测试 小结 概述 单一职责原则(Single Responsibility P ...

  8. 设计模式 - 六大设计原则之OCP(开闭原则)

    文章目录 概述 Case 接口定义 接口实现 Bad Impl Better Impl 概述 Open-Close Principle 在面向对象编程领域中,开闭原则规定软件中的类.对象.模块和函数对 ...

  9. 设计模式 - 六大设计原则之LoD(迪米特法则原则)

    文章目录 概述 Case 学生类 老师类 Bad Impl Better Impl 老师类改造 调用方:校长类改造 概述 迪米特法(Law Of Demeter , LoD)则又叫最少知道原则(Lea ...

最新文章

  1. hihoCoder - 1082 - 然而沼跃鱼早就看穿了一切 (字符串处理!!)
  2. 调用Com+时提示找不到文件
  3. 初学者不建议月python吗_9.python入门
  4. 计算机408考研专题(建议收藏)
  5. HTTP状态码的类别
  6. svn忽略指定文件夹下的文件_管理SteamLibrary文件夹下的acf文件
  7. android布局属性详解(转)
  8. leetcode —— 1319. 连通网络的操作次数
  9. sqlmap md5怎么解密_三十九,hackthebox渗透之DirBuster扫描路径及Sqlmap
  10. html邮件模板美化,设计利器:定制你的炫酷邮件模板
  11. Android 标题下划线 选中效果
  12. 计算机if函数得出三个结果,Excel如果if函数有多个条件,应该怎么使用
  13. Linux笔记:文本编辑器nano简单说明
  14. 十年测试经验的阿里p10讲解python初阶:函数和模块 python全栈自动化测试系类4-2
  15. 什么是EDID,EDID能做什么,EDID基本介绍
  16. double类型大小比较的方法
  17. 满足你的好奇,手动拆解示波器,了解机内高科技
  18. 360安全卫士的云查杀原理介绍[转]
  19. Honeywell EPKS R5XX 系统装机及配置手册
  20. 闪迪u盘格式化 linux,u盘 32g 闪迪cz80linux u盘挂载

热门文章

  1. epass1000 初始化 验证
  2. UI设计用什么软件?这3个必用!
  3. php mysql存储过程写法_mysql存储过程写法
  4. html弹窗是否删除,javascript删除前弹出确认/取消询问窗口confirm
  5. Juc09_CompletableFuture概述、创建方式、常用API、电商比价需求
  6. 我的又一个iPhone程序正式上线了
  7. DAO PO BO DTO VO DO的区别
  8. 元宇宙产业链(含205页PPT)!
  9. 原生js+div+css,动态画结构图/流程图
  10. Postman 工具入门学习