设计模式七大原则解读(二)

简介: 设计模式七大原则解读(二)

依赖倒转原则

基本介绍

依赖倒转原则(Dependence Inversion Principle)是指:
1) 高层模块不应该依赖低层模块,二者都应该依赖其抽象
2) 抽象不应该依赖细节,细节应该依赖抽象
3) 依赖倒转(倒置)的中心思想是面向接口编程
4) 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类

5) 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

应用实例

请编程完成 Person 接收消息的功能

1) 实现方案 1 + 分析说明

1. public class DependecyInversion {
2. public static void main(String[] args) {
3. 
4.     }
5. }
6. class Email {
7. public String getInfo() {
8. return "电子邮件信息: hello,world";
9.     }
10. }
11. 
12. class Person {
13. public void receive(Email email ) {
14.         System.out.println(email.getInfo());
15.     }
16. }

方式 1 分析
1. 简单,比较容易想到
2. 如果我们获取的对象是 微信,短信等等,则新增类,同时 Perons 也要增加相应的接收方法
3. 解决思路:引入一个抽象的接口 IReceiver, 表示接收者, 这样 Person 类与接口 IReceiver 发生依赖,因为 Email, WeiXin 等等属于接收的范围,他们各自实现 IReceiver 接口就 ok, 这样我们就符号依赖倒转原则

2) 实现方案 2(依赖倒转) + 分析说明

1. public class DependecyInversion2 {
2. public static void main(String[] args) {
3. //客户端无需改变
4. Person person = new Person();
5.         person.receive(new Email2());
6.         person.receive(new WeiXin2());
7.     }
8. }
9. //定义接口
10. interface IReceiver {
11. public String getInfo();
12. }
13. class Email2 implements IReceiver {
14. public String getInfo() {
15. return "电子邮件信息: hello,world";
16.     }
17. }
18. //增加微信
19. class WeiXin2 implements IReceiver {
20. public String getInfo() {
21. return "微信信息: hello,ok";
22.     }
23. }
24. //方式 2
25. class Person2 {
26. //这里我们是对接口的依赖
27. public void receive(IReceiver receiver ) {
28.         System.out.println(receiver.getInfo());
29.     }
30. }

3)依赖关系传递的三种方式和应用案例

1) 接口传递==》应用案例代码

1. interface IOpenAndClose {
2. public void open(ITV tv); //抽象方法,接收接口
3. }
4. 
5. interface ITV { //ITV 接口
6. public void play();
7. }
8. 
9. class ChangHong implements ITV {
10. 
11. @Override
12. public void play() {
13. // TODO Auto-generated method stub
14.         System.out.println("长虹电视机,打开");
15.     }
16. 
17. }
18. // 实现接口
19. class OpenAndClose implements IOpenAndClose {
20. public void open(ITV tv) {
21.         tv.play();
22.     }
23. }

2) 构造方法传递==》应用案例代码

1. // 方式 2: 通过构造方法依赖传递
2. interface IOpenAndClose {
3. public void open(); //抽象方法
4. }
5. 
6. interface ITV { //ITV 接口
7. public void play();
8. }
9. 
10. class OpenAndClose implements IOpenAndClose {
11. public ITV tv; //成员
12. 
13. public OpenAndClose(ITV tv) { //构造器
14. this.tv = tv;
15.     }
16. 
17. public void open() {
18. this.tv.play();
19.     }
20. }

3) setter 方式传递==》应用案例代码

1. // 方式 3 , 通过 setter 方法传递
2. interface IOpenAndClose {
3. public void open(); // 抽象方法
4. 
5. public void setTv(ITV tv);
6. }
7. 
8. interface ITV { // ITV 接口
9. public void play();
10. }
11. 
12. class OpenAndClose implements IOpenAndClose {
13. private ITV tv;
14. 
15. public void setTv(ITV tv) {
16. this.tv = tv;
17.     }
18. 
19. public void open() {
20. this.tv.play();
21.     }
22. }
23. 
24. class ChangHong implements ITV {
25. @Override
26. public void play() {
27. // TODO Auto-generated method stub
28.         System.out.println("长虹电视机,打开");
29.     }
30. }

依赖倒转原则的注意事项和细节

1) 低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好.

2) 变量的声明类型尽量是抽象类或接口, 这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化

3) 继承时遵循里氏替换原则

里氏替换原则

OO 中的继承性的思考和说明

1) 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
2) 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障
3) 问题提出:在编程中,如何正确的使用继承? => 里氏替换原则

基本介绍

1) 里氏替换原则(Liskov Substitution Principle)在 1988 年,由麻省理工学院的以为姓里的女士提出的。
2) 如果对每个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
3) 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
4) 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。

一个程序引出的问题和思考

该看个程序, 思考下问题和解决思路

1. public class Liskov {
2. public static void main(String[] args) {
3. // TODO Auto-generated method stub
4. A a = new A();
5.         System.out.println("11-3=" + a.func1(11, 3));
6.         System.out.println("1-8=" + a.func1(1, 8));
7.         System.out.println("-----------------------");
8. B b = new B();
9.         System.out.println("11-3=" + b.func1(11, 3));//这里本意是求出 11-3
10.         System.out.println("1-8=" + b.func1(1, 8));// 1-8
11.         System.out.println("11+3+9=" + b.func2(11, 3));
12.     }
13. }
14. 
15. // A 类
16. class A {
17. // 返回两个数的差
18. public int func1(int num1, int num2) {
19. return num1 - num2;
20.     }
21. }
22. 
23. // B 类继承了 A
24. // 增加了一个新功能:完成两个数相加,然后和 9 求和
25. class B extends A {
26. //这里,重写了 A 类的方法, 可能是无意识
27. public int func1(int a, int b) {
28. return a + b;
29.     }
30. 
31. public int func2(int a, int b) {
32. return func1(a, b) + 9;
33.     }
34. }

我们发现原来运行正常的相减功能发生了错误。原因就是类 B 无意中重写了父类的方法,造成原有功能出现错误。在实际编程中,我们常常会通过重写父类的方法完成新的功能,这样写起来虽然简单,但整个继承体系的复用性会比较差。特别是运行多态比较频繁的时候

相关文章
|
6月前
|
设计模式 前端开发 Java
设计模式之六大基本原则
设计模式之六大基本原则
50 0
|
3月前
|
设计模式
设计模式七大原则
这篇文章介绍了设计模式中的七大原则,特别强调了单一职责原则,即一个类应该只有一个引起其行为变化的原因,以确保类功能的高内聚和低耦合。
|
3月前
|
设计模式 存储 前端开发
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
|
2月前
|
设计模式 Java 关系型数据库
设计模式——设计模式简介和七大原则
设计模式的目的和核心原则、单一职责原则、接口隔离原则、依赖倒转原则、里氏替换原则、开闭原则、迪米特法则、合成复用原则
设计模式——设计模式简介和七大原则
|
5月前
|
设计模式 供应链
设计模式六大原则之迪米特法则
设计模式六大原则之迪米特法则
|
5月前
|
设计模式
设计模式六大原则之依赖倒置原则
设计模式六大原则之依赖倒置原则
|
3月前
|
设计模式 算法 开发者
设计模式问题之最小知识原则(迪米特法则)对代码设计有何影响,如何解决
设计模式问题之最小知识原则(迪米特法则)对代码设计有何影响,如何解决
|
3月前
|
设计模式 前端开发 JavaScript
React开发设计模式及原则概念问题之什么是HOC(Higher-order component),HOC遵循的设计原则都有哪些
React开发设计模式及原则概念问题之什么是HOC(Higher-order component),HOC遵循的设计原则都有哪些
|
3月前
|
设计模式 前端开发 JavaScript
React开发设计模式及原则概念问题之什么是设计模式,单一职责原则如何理解
React开发设计模式及原则概念问题之什么是设计模式,单一职责原则如何理解
|
5月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
37 2

热门文章

最新文章

  • 1
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    45
  • 2
    C++一分钟之-C++中的设计模式:单例模式
    51
  • 3
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    36
  • 4
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    59
  • 5
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    54
  • 6
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    39
  • 7
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    49
  • 8
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    102
  • 9
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    74
  • 10
    Go语言设计模式:使用Option模式简化类的初始化
    71