一、设计模式的目的 编写软件过程中,程序员面临着来自耦合性、内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好的
1) 代码重用性 (即:相同功能的代码,不用多次编写)
2)可读性(即:编程规范性,便于其他程序员的阅读和理解)
3)可扩展性(即:当我们要增加新的功能时,非常的方便,称为可维护)
4)可靠性(即:当我们增加新的功能后,对原来的功能没有影响)
5)使程序呈现高内聚,低耦合的特性
设计模式包含了面向对象的精髓,“懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要”
二、设计模式七大原则 设计模式原则,其实就是程序员在编程时,应当遵守的原则,也是各种设计模式的基础(即:设计模式为什么这样设计的依据)
设计模式常用的七大原则有:
1)单一职责原则
2)接口隔离原则
3)依赖倒转(倒置)原则
4)里氏替换原则
5)开闭原则
6)迪米特法则
7)合成复用原则
三、单一职责原则 3.1. 基本介绍 对类来说,即一个类应该只负责一项职责。如果类 A 负责两个不同的职责:职责 1,职责 2 。当职责 1 需要变更改变 A 时,可能造成职责 2 执行错误,所以需要将类 A 的粒度分解为 A1,A2 。
3.2. 应用实例 以交通工具案例讲解
1)方案 1 【分析说明】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package cn.hunkier.principle.singleresponsibility;public class SingleResponsibility1 { public static void main (String[] args) { Vehicle vehicle = new Vehicle(); vehicle.run("摩托车" ); vehicle.run("汽车" ); vehicle.run("飞机" ); } } class Vehicle { public void run (String vehicle) { System.out.println(vehicle + "在公路上运行..." ); } }
2) 方案 2 【分析说明】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package cn.hunkier.principle.singleresponsibility;public class SingleResponsibility2 { public static void main (String[] args) { RoadVehicle roadVehicle = new RoadVehicle(); roadVehicle.run("摩托车" ); roadVehicle.run("汽车" ); AirVehicle airVehicle = new AirVehicle(); airVehicle.run("飞机" ); } } class RoadVehicle { public void run (String vehicle) { System.out.println(vehicle + "公路运行" ); } } class AirVehicle { public void run (String vehicle) { System.out.println(vehicle + "天空运行" ); } } class WaterVehicle { public void run (String vehicle) { System.out.println(vehicle + "水中运行" ); } }
3) 方案 3 【分析说明】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package cn.hunkier.principle.singleresponsibility;public class SingleResponsibility3 { public static void main (String[] args) { Vehicle2 vehicle2 = new Vehicle2(); vehicle2.run("汽车" ); vehicle2.runWater("轮船" ); vehicle2.runAir("飞机" ); } } class Vehicle2 { public void run (String vehicle) { System.out.println(vehicle + " 在公路上运行..." ); } public void runAir (String vehicle) { System.out.println(vehicle + " 在天空上运行..." ); } public void runWater (String vehicle) { System.out.println(vehicle + " 在水中运行..." ); } }
3.3. 单一职责原则注意事项和细节
降低类的复杂度,一个类只负责一项职责。
提高类的可读性,可维护性
降低变更引起的风险
通常情况下,我们应该遵守单一职责原则,只有逻辑足够简单,才可以在代码级别违反单一职责原则:只有类中方法数量足够少,可以在方法级别保持单一职责原则
四、 接口隔离原则 4.1. 基本介绍 1)客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
2)类 A 通过接口 Interface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,如果接口 Interface1 对于类 A 和类 C 来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法。
3)按隔离原则应当这样处理:
将接口 Interface1 拆分为独立的几个接口(这里我们拆分为 3 个接口),类 A 和 类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
4.2. 应用实例 1)类 A 通过接口 Interface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,请编写代码完成此应用实例。
2)没有使用接口隔离原则代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 package cn.hunkier.principle.segregation;public class Segregation1 { public static void main (String[] args) { } } Interface Interface1{ void operation1 () ; void operation2 () ; void operation3 () ; void operation4 () ; void operation5 () ; } class B implements Interface1 { public void operation1 () { System.out.println("B 实现了 operation1" ); } public void operation2 () { System.out.println("B 实现了 operation2 " ); } public void operation3 () { System.out.println("B 实现了 operation3 " ); } public void operation4 () { System.out.println("B 实现了 operation4 " ); } public void operation5 () { System.out.println("B 实现了 operation5 " ); } } class D implements Interface1 { public void operation1 () { System.out.println("D 实现了 operation1" ); } public void operation2 () { System.out.println("D 实现了 operation2 " ); } public void operation3 () { System.out.println("D 实现了 operation3 " ); } public void operation4 () { System.out.println("D 实现了 operation4 " ); } public void operation5 () { System.out.println("D 实现了 operation5 " ); } } class A { public void depend1 (Interface1 i) { i.operation1(); } public void depend2 (Interface1 i) { i.operation2(); } public void depend3 (Interface1 i) { i.operation3(); } } class C { public void depend1 (Interface1 i) { i.operation1(); } public void depend4 (Interface1 i) { i.operation5(); } public void depend5 (Interface1 i) { i.operation5(); } }
4.3. 使用传统方法的问题和使用接口隔离原则改进 1)类 A 通过接口 Ingerface1 依赖类 B,类 C 通过接口 Interface1 依赖类 D,如果接口 Interface1 对于类 A 和 类 C来说不是最小接口,那么类 B 和类 D 必须去实现他们不需要的方法
2)将接口 Interface1 拆分为独立的几个接口,类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
3)接口 Interface1 中出现的方法,根据实际情况拆分为三个接口:接口 Interface1 包含方法 operation1,Interface2 包含方法 operation2、operation3,接口 Interface3 包含方法 operation4、operation5
4)代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 package cn.hunkier.principle.segregation.improve;public class Segregation1 { public static void main (String[] args) { A a = new A(); a.depend1(new B()); a.depend2(new B()); a.depend3(new B()); C c = new C(); c.depend1(new D()); c.depend4(new D()); c.depend5(new D()); } } interface Interface1 { void operation1 () ; } interface Interface2 { void operation2 () ; void operation3 () ; } interface Interface3 { void operation4 () ; void operation5 () ; } class B implements Interface1 , Interface2 { public void operation1 () { System.out.println("B 实现了 operation1 " ); } public void operation2 () { System.out.println("B 实现了 operation2 " ); } public void operation3 () { System.out.println("B 实现了 operation3 " ); } } class D implements Interface1 , Interface2 { public void operation1 () { System.out.println("D 实现了 operation1 " ); } public void operation4 () { System.out.println("D 实现了 operation4 " ); } public void operation5 () { System.out.println("D 实现了 operation5 " ); } } class A { public void depend1 (Interface1 i) { i.operation1(); } public void depend2 (Interface2 i) { i.operation2(); } public void depend3 (Interface2 i) { i.operation3(); } } class C { public void depend1 (Interface1 i) { i.operation1(); } public void depend4 (Interface3 i) { i.operation4(); } public void depend5 (Interface3 i) { i.operation5(); } }
5. 依赖倒转原则 5.1. 基本介绍 依赖倒转原则(Dependence Inversion Principle)是指:
1)高层模块不应该依赖底层模块,二者都应该依赖器抽象
2)抽象不应该依赖细节,细节应该依赖抽象
3)依赖倒转(倒置)的中心思想是面向接口编程
4)依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 Java 中,抽象指的是接口或者抽象类,细节就是具体的实现类
5)使用接口或者抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给实现类去完成
5.2. 应用实例 请编程完成 Person 接收消息的功能。
1)实现方案 1 + 分析说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package cn.hunkier.principle.inversion;public class DependecyInversion { public stativ void main (String[] args) { Person person = new Person(); person.receive(new Email()); } } class Email { public String getInfo () { return "电子邮件信息:hello,world" ; } } class Person { public void receive (Email email) { System.out.println(email.getInfo()); } }
实现方案 2 (依赖倒转)+ 分析说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package cn.hunkier.principle.inversion.improve;public class DependecyInversion { public static void main (String[] args) { Person person = new Person(); person.receive(new Email()); person.receive(new Weixin()); } } interface IReceiver { public String getInfo () ; } class Email implements IReceiver { public String getInfo () { return "电子邮件信息:hello,world" ; } } class Weixin implements IReceiver { public String getInfo () { return "微信消息:hello,ok" ; } } class Person { public void receive (IReceiver receiver) { System.out.println(receiver.getInfo()); } }
5.3. 依赖关系传递的三种方式和应用案例 1)接口传递
应用案例代码
2)构造方法传递
应用案例代码
3) setter 方式传递
应用案例代码
4)代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 package cn.hunkier.principle.inversion.improve;public class DependencyPass { public static void main (String[] args) { ChangHong changhong = new ChangHong(); OpenAndClose openAndClose = new OpenAndClose(); openAndClose.setTv(changHong); openAndClose.open(); } } interface IOpenAndClose { }