课程链接:https://www.bilibili.com/video/BV1G4411c7N4?p=8&spm_id_from=pageDriver
一、引子
1.1 设计模式常用的七大原则有:
- 1) 单一职责原则
- 2) 接口隔离原则
- 3) 依赖倒转原则
- 4) 里氏替换原则
- 5) 开闭原则ocp
- 6) 迪米特法则
- 7) 合成复用原则
1.2 几个经典的设计模式面试题
1.2.1 金融借贷平台项目——状态模式
借贷平台的订单,有审核发布抢单等等步骤,随着操作的不同,会改变订单的状态,项目中的这个模块实现就会使用到状态模式,请你使用状态模式进行设计,并完成实际代码
问题分析
这类代码难以应对变化,在添加一种状态时,我们需要手动添加if/else,在添加一种功能时,要对所有的状态进行判断。因此代码会变得越来越臃肿,并且-旦没有处理某个状态,便会发生极其严重的BUG,难以维护
1.2.2 解释器设计模式
- 1)介绍解释器设计模式是什么?
- 2)画出解释器设计模式的UML类图,分析设计模式中的各个角色是什么?
- 3)请说明Spring的框架中,哪里使用到了解释器设计模式,并做源码级别的分析
1.2.3 单例设计模式
一共有几种实现方式?请分别用代码实现,并说明各个实现方式的优点和缺点
单例设计模式一共有8种写法,后面我们会依次讲到
- 1)饿汉式两种I
- 2)懒汉式三种
- 3)双重检查
- 4)静态内部类
- 5)枚举
二、七大设计原则介绍
2.1 设计模式的目的
编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好
- 1) 代码重用性(即:相同功能的代码,不用多次编写)
- 2) 可读性(即:编程规范性,便于其他程序员的阅读和理解)
- 3) 可扩展性(即:当需要增加新的功能时,非常的方便,称为可维护
- 4) 可靠性(即:当我们增加新的功能后,对原来的功能没有影响)
- 5) 使程序呈现高内聚,低耦合的特性
2.2 设计模式常用的七大原则有:
- 1) 单一职责原则
- 2) 接口隔离原则
- 3) 依赖倒转(倒置)原则
- 4) 里氏替换原则
- 5) 开闭原则
- 6) 迪米特法则
- 7) 合成复用原则
2.2.1 单一职责原则
对类来说的,即一个类应该只负责一项职责(不是说一个类里只能有一个方法,指的是一项职责,比如这个类管订单了,就不要去管物流。),如类A负责两个不同职责: 职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为 A1,A2
单一职责原则注意事项和细节
- 1)降低类的复杂度,一个类只负责一项职责。
- 2)提高类的可读性,可维护性
- 3)降低变更引起的风险
- 4)通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一-职责原则
例子
// 方式1
// 1.在方式1的run方法中,违反了单一职责原则
// 2. 解决的方案非常的简单,根据交通工具运行方法不同,分解成不同类即可
class Vehicle {
public void run(String vehicle)
System.out.println(vehicle+"在公路上运行..");
}
}
// 方案2的分析
// 1.遵守单- -职责原则
// 2.但是这样做的改动很大,即将类分解,同时修改客户端
// 改进:直接修改Vehicle类,改动的代码会比较少=>方案3
class WaterVelhjicle {
public void run(String vehicle) {
System.out.println(vehicle + "水中运行");
}
}
class AirVehicle {
public void run(String vehicle) {
System.out.println(vehicle + "天空运行");
}
}
// 方式3
// 1.这种修改方法没有对原来的类做大的修改,只是增加方法
// 2. 这里虽然没有在类这个级别上遵守单一 职责原则,但是在方法级别上,仍然是遵守单一职责
class Vehicle2 {
public void run(String vehicle) {
//处理
System.out.println(vehicle+"在公路上运行..");
}
public void runAir(String vehicle) {
System.out.println(vehicle+"在天空上运行...");
}
}
2.2.2 接口隔离原则
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上
例子
下图是我们编码中遇到的常见问题:
类A通过接口Interface1依赖类B,类c通过接OInterface1依赖类D,如果接口Interface1对于类A和类c来说不是最小接口那么类B和类D必须去实现他们不需要的方法。
//接口
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
class B implements Interface1 {
void operation1() {
System. out. println();
}
void operation2(){
System. out. println();
}
void operation3(){
System. out. println();
}
void operation4(){
System. out. println();
}
void operation5() {
System. out. println();
}
}
class D implements Interface1 {
void operation1() {
System. out. println();
}
void operation2(){
System. out. println();
}
void operation3(){
System. out. println();
}
void operation4(){
System. out. println();
}
void operation5() {
System. out. println();
}
}
class A { //A 类通过接口Interface1依赖(使用) B类,但是只会用到1,2,3方法
public void depend1(Interface1 i) {
i. operation1();
}
public void depend2(Interface1 i) {
i. operation2();
}
public void depend3(Interface1 i) {
i. operation3();
}
}
class D { //D 类通过接口Interface1依赖(使用) D类,但是只会用到1,4,5方法
public void depend1(Interface1 i) {
i. operation1();
}
public void depend2(Interface1 i) {
i. operation4();
}
public void depend3(Interface1 i) {
i. operation5();
}
}
按隔离原则应当这样处理:
将接口Interface1 拆分为独立的几个接口,类A和类c分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则
interface Interface1 {
void operation1();
}
//接口2
interface Interface2 {
void operation2();
void operation3();
}
//接口3
interface Interface3 {
void operation4();
void 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();
}
}
未完待续 2021 03 16
类之间的关系
依赖——a依赖b,说明a使用b (dependency)