一、介绍

概念:一个类的接口转换成客户端希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。即根据已有的接口,生成想要的接口。

先看下面这个小例子体会一下适配器模式:

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
public class AppTest {
/**
*
* 符合开闭原则,源代码没有进行修改
* 也符合组合优于继承原则(只是进行复用)
*/
public static void main(String[] args) {
Calculate calculate = new Calculate(); // 原来的接口是接两个
CalcAdapter calcAdapter = new CalcAdapter(calculate); // 做个适配器,可以接收三个
int add = calcAdapter.add(1, 2, 3);
System.out.println(add);
}
}

// 基本计算器
class Calculate {
public int add(int a, int b) {
return a + b;
}
}

// 变化来了,客户想要计算三个数的和 - 采用适配器模式的方式,将接口转换成我们需要的形式
class CalcAdapter {
private Calculate calculate; // 复用其功能,采用组合的方式。组合需要被是适配的类

public CalcAdapter(Calculate calculate) {
this.calculate = calculate;
}

public int add(int a, int b, int c) {
return calculate.add(a, calculate.add(b, c)); // 做到对功能的复用
}
}

一、开闭原则

1.1 概念

开闭原则是设计模式中最重要也是最基本的原则,可以说其它的原则都是为了开闭原则进行服务的。

核心概念:

  1. 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。对抽象构建框架,用实现扩展细节。
  2. 当软件需要实现时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  3. 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

综合:对扩展新功能是开放的,对修改原有功能是关闭的。也就说,在对功能进行扩展时,是对原有的类上进行扩展(继承、接口设计等等)

本文用来记录工厂模式中,简单工厂、工厂方法和抽象工厂。

一、前置知识

image-20210710144613164

上图中,每个功能可以看成一个模块,每个模块要想能正常、更好的使用,一定也会依赖其他的模块,所以需要满足:

  • 每个模块负责自己的职责(单一职责),各个模块之间通过接口隔离原则对外暴露功能的使用(接口隔离原则)。
  • 每个模块都应该”承诺”自己对外暴露的接口是不变的。当模块内部发生变化时,其他模块是不需要知道的。这便是依赖于抽象而不依赖于实现(依赖倒置原则)
  • 上层模块只需要知道下层模块暴露出的接口即可,至于实现细节不需要也不应该知道。(迪米特法则)

为了对下面的实例代码进行演示,先明确两个概念:

  1. 产品:对应着类。
  2. 抽象产品:抽象类或接口

需求:

设计一个食物的项目,便于食物种类的扩展,且便于维护。

  1. 食物存在各种各样的种类
  2. 客户端可以对其进行扩展自己所需要的食物。

本文用来介绍设计模式中的单例模式。

一、基本介绍

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法)。

并且常见的单例设计模式共有八种:

  • 饿汉式(静态常量)
  • 饿汉式(静态代码块的方式)
  • 懒汉式(线程不安全)
  • 懒汉式(线程安全,同步方法)
  • 懒汉式(线程安全,同步代码块)
  • 双重检查
  • 静态内部类
  • 枚举

接下来,我们将逐一介绍这八种单例设计模式。

单例模式设计步骤如下:

  1. 构造器私有化(防止new)
  2. 类的内部创建对象
  3. 向外暴露一个静态的公共方法。

本章用来叙述设计模式中的接口隔离原则。叙述方式同样采用实例演示的方式。

一、基本介绍

接口隔离原则的核心:客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。

二、实例介绍

我们现在设计一个接口,接口中有5个功能,分别让B,D类实现这个接口;然后,我们再设计A,C类,其中A,C类分别依赖B,D类;A使用B类中的option1,option2,option3方法;C使用D类中option1,option4,option5方法。

本文用来讲述设计模式中的依赖倒置原则。通过介绍,场景,代码推进的方式进行一步步的讲解。

一、介绍

依赖倒置原则(Dependence Inversion Principle)是指:

  1. 高层模块不应该依赖底层模块,二者都应该依赖其抽象。这里调用者就是上层,被调用者就是下层。
  2. 抽象不应该依赖细节,细节应该依赖抽象。(抽象是指接口或者抽象类,细节是指具体实现及使用)
  3. 依赖倒置的中心思想是面向接口编程
  4. 依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类
  5. 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
  6. 使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

本章用来讲述设计模式中的另一个原则——组合优于继承原则,又称为合成复用原则。

一、基本介绍

该原则是尽量使用合成/聚合的方式,而不是使用继承。

上面一句话就是对该原则的核心,但单单看这么一句话还是显得过于枯燥与不知所云,下面我们还是结合具体的场景进行代码推进,对该原则进行讲解。

二、场景

假设我们需要设计这样一个集合,每次向里面加入元素时,count都加一。例如:

最初集合是空集合,此时我们向里面加入"a",此时集合为{"a"},那么此时count = 1;当加入"b","c"两个元素时,集合为{"a","b","c"},此时count=3;此时再删除"a","c"两个元素,集合为{"b"},count仍然等于3;最后再加入"d",集合为{"b","d"}count=4

所以该场景是,不论中间是否删除元素,我们只统计加入到集合中的元素的次数,进行返回。

在对设计模式的学习中,首先需要了解、掌握设计模式的七大原则,这样后续对设计模式的学习才能够更加的轻松与透彻。本章用于总结设计模式中的单一职责原则,该原则也是比较容易理解的。

一、基本介绍

对类来说的,即一个类应该只负责一项职责。如类 A 负责两个不同职责:职责 1,职责 2。当职责 1 需求变更而改变 A 时,可能造成职责 2 执行错误,所以需要将类 A 的粒度分解为 A1,A2。

二、场景应用

2.1 场景一

该场景模拟交通工具使用场景。

目的:模拟交通工具的运输形式。

反例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingleExample {

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 + "在公路上运行");
}
}