设计模式

设计模式

  • 依赖和关联(简单理解):当A使用B作为变量或者方法参数,叫依赖关系。当A使用B作为类属性,则叫关联关系,关联关系是一种强依赖关系。
  • 多态的向上转型:父类类型 父类引用名 = new 子类类型();
    • 编译阶段看左边的父类型,所以不能调用子类特有的成员,否则编译不通过
    • 运行阶段看右边的子类型,调用方法从子类开始查找,一般调用子类重写的方法,属性无重写

1. 单例模式

  • 理解:单例模式确保某一个类只有一个实例,自行实例化,给系统提供全局访问方法

  • 例子:任务管理器、身份证、打印池

  • 优缺点

    • 缺点:违反“单一职责原则”
  • 类图:见书

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class Singleton
    {
    private static Singleton instance = null; // 静态私有成员变量
    // 私有构造函数
    private Singleton(){

    }
    // 静态公有工厂方法,返回唯一实例
    public static Singleton getInstance(){
    if(instance == null)
    instance = new Singleton();
    return instance;
    }
    }
  • 测试:

    1
    2
    3
    4
    5
    6
    7
    public class Singleton{
    public static void main(String a[]){
    Singleton s1 = Singleton.getInstance();
    Singleton s2 = Singleton.getInstance();
    System.out.println(s1 == s2);
    }
    }

2. 迭代器模式

  • 理解:聚合对象有两个功能:一是存储内部数据,二是遍历内部数据。把遍历行为提取成为迭代器。
  • 大概率只考察类图:抽象和具体迭代器 and 抽象和具体聚合类
  • 例子:迭代器——电视遥控器 聚合类————电视机
  • 代码理解:
    • 抽象迭代器只有抽象迭代方法声明,抽象聚合类只有抽象创建迭代器方法声明
    • 具体聚合类:一是有数据,二是实现创建具体迭代器(返回一个具体迭代器对象),三是包含具体迭代器的类(即内部类的方式,也可以用另一种方式,单独写一个具体迭代器类,初始化需要具体聚合类参数)image-20240226235952395

3. 策略模式

  • 理解:将一系列算法封装起来,由环境类(使用算法的角色)选择使用哪种算法

  • 例子:环境类(数组处理类)、抽象策略类、具体策略类(冒泡插入选择排序)

    image-20240227000013615

  • 代码理解:

    • 环境类有set方法,用于设置具体策略类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Context{ // 环境类
    private Strategy strategy;

    public void setStrategy(Strategy strategy){
    this.strategy = strategy;
    }
    private void contextAlgorithm(...){
    strategy.algorithm(...);
    }
    }
    public interface Strategy{ // 抽象策略类 or 策略类接口
    public void algotithm(...);
    }
    public class StrategyA implements Strategy{ // 具体策略类A
    public void algotithm(...){
    ...
    };
    }
    public class StrategyB implements Strategy{ // 具体策略类B
    public void algotithm(...){
    ...
    };
    }

  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    public class Client{
    public static void main(){
    Context c = new Context();
    StrategyA sa = new StrategyA();
    c.setStrategy(sa);
    c.contextAlgorithm(...);
    }
    }

4. 工厂模式

  • 三个模式之间的关系:

    • 当抽象工厂模式每一个具体工厂类只创造一个产品对象,抽象工厂退化为工厂方法模式
    • 当工厂方法模式抽象工厂与具体工厂合并,只有一个统一的工厂来创建产品对象,工厂方法模式退化为简单工厂模式
  • 关于抽象工厂模式是否符合开闭原则

    • 如果增加产品族(由一个工厂生产的所有商品),只需要增加具体工厂,符合OCP
    • 如果增加产品等级结构(同一种商品),要修改所有工厂类,不符合OCP
  • 关于工厂模式与策略模式的比较:工厂模式用于创建对象,策略模式用于选择各种方法

  • 工厂方法UML图:

    image-20240227000030157

5. 观察者模式

  • 很好理解

  • 例子:主题类(猫),观察者(老鼠、狗)猫叫后老鼠和狗都有动作

  • 类图:抽象主题(观察者数组、增加、删除观察者)、抽象观察者、具体主题(提醒观察者)、具体观察者

    image-20240227000127357

  • 代码示例:

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
// 抽象目标类
public abstract class MySubject {
protected ArrayList observers = new ArrayList();

// 注册观察者
public void attach(MyObserver observer) {
observers.add(observer);
}

// 删除观察者
public void detach(MyObserver observer) {
observers.remove(observer);
}

public abstract void cry();
}

// 抽象观察者(接口)
public interface MyObserver {
void response();
}

// 具体主题
public class Cat extends MySubject{

@Override
public void cry() {
System.out.print("猫叫!!!");
System.out.print("---------------------");

for(Object obs:observers) {
((MyObserver)obs).response();
}

}

}
// 具体观察者
public class Dog implements MyObserver{

@Override
public void response() {
// TODO Auto-generated method stub
System.out.print("狗也开始叫!!!");
}

}
// 具体观察者2
public class Mouse implements MyObserver{

@Override
public void response() {
// TODO Auto-generated method stub
System.out.print("老鼠赶紧逃跑!");
}

}
// 客户端测试类
public class Client {

public static void main(String[] args) {
MySubject subject = new Cat();

MyObserver obs1, obs2, obs3;
obs1 = new Mouse();
obs2 = new Mouse();
obs3 = new Dog();

subject.attach(obs1);
subject.attach(obs2);
subject.attach(obs3);

subject.cry();

subject.detach(obs3);

subject.cry();
}

}

6. 建造者模式

  • 和工厂模式很像,也是对象创建型模式,创建复杂的对象,关注各个配件的创建,有一个指挥者

7. 原型模式

  • 通过复制(clone)原型来创建对象

8. 适配器模式

  • 让目标类可以做适配类的行为,类适配要用接口,对象适配只用继承

  • 分为类适配器和对象适配器

    • 类适配器实现目标类,继承适配类的接口(比如让robot可以学dog叫,因为狗叫是dog已实现的方法,所以继承dog,实现robot)(抽象和实现的区别:抽象可以选择父类方法调用,实现必须实现接口所有方法)
    • 对象适配器继承目标类,关联适配类(把适配类当作变量)
  • 使用时候,用目标类作为父类创建适配器

  • 类图:

    image-20240227000141080

9. 桥接模式

  • 一个类有两个独立变化的维度,把两个维度分离开,独立扩展

  • 抽象化:把类的共同性质抽取出来形成抽象类,比如不同颜色的毛笔都是毛笔

  • 实现类:另一个维度的实现部分,比如毛笔的颜色

  • 抽象类与实现类有聚合关系(桥)

  • 例子:不同操作系统上播放多种格式的视频文件、描述不同制造商以及制造的电器种类

  • 类图

    image-20240227000150502

10. 组合模式

  • 想到组合模式就应该想到树形结构图,对叶子和容器的使用要有一致性

  • 用抽象构件作为叶子和容器的抽象,容器和构件建立组合关系,容器有构件的数据可以遍历

  • 例子:水果盘里有水果和水果盘;文件夹浏览和文件浏览方式;

  • 类图

    image-20240227000200509

11. 装饰模式

  • 对原有对象的功能进行扩展

  • 对类功能进行复用时应该多用关联关系,少用继承关系

  • UML图和组合模式很像,但原理不同

  • 抽象构件有一个默认具体构件类,比如煎饼果子默认加蛋

  • 理解:咖啡加很多调料,如果用继承关系,把各种调料方式的咖啡都建立一个子类,会有类爆炸。所以使用装饰模式,建立各种调料的类,用调料调用咖啡进行装饰。

  • 例子:变形金刚;

  • 类图(抽象装饰类和具体装饰类的初始化有说法)

    image-20240227000208991

12. 外观模式

  • 对外提供一个统一的接口用来访问子系统

  • 对客户屏蔽子系统组件,降低客户类与子系统类的耦合度

  • eg:网站首页有各个子栏目;电源总开关控制很多子开关

  • UML图很简单,外观类关联很多子系统类

  • 违反OCP,增加子系统会修改外观类代码,抽象外观模式符合OCP

  • 体现单一职责,体现迪米特

    image-20240227000217504

13. 代理模式

  • 代理对象控制对对象的访问

  • 很简单:代理对象有对象的变量,自己有控制等级变量,根据控制等级,调用对象的方法。因为要满足OCP所以继承一个抽象对象

  • 客户端调用代理对象,完成对对象的代理访问

    image-20240227000224921

14. 命令模式

  • 将一个请求封装成一个对象,发送请求的对象只需要知道如何发送请求,不必知道如何完成请求

  • 分为请求发送控制者和请求接收者,抽象请求和具体请求。发送者有很多请求对象,请求对象有发送接收者成员变量。发送者调用请求,请求调用接收者的方法

  • 客户端建立请求控制对象,建立请求,初始化请求控制对象

    image-20240227000331277

15. 中介者模式

  • 中介者模式可以使对象之间的关系数量急剧减少,变成以中介者为中心的星状结构(私聊变群聊)

  • 分为抽象中介和具体中介、抽象同事和具体同事,具体中介有同事数组作为成员变量,抽象同事有抽象中介作为成员变量,用来调用中介的方法进行通信

  • 考代码的话稍微有点复杂,画类图很简单

    image-20240227000339228

16. 备忘录模式

17. 状态模式

  • 对象在不同状态下的行为不同,且可以自动转换状态

  • 例子:论坛用户等级、银行账户状态、两个开关同时开关

  • 优缺点

    • 缺点:对开闭原则支持不太好,可以切换状态的状态模式,增加状态需要修改负责状态转换的代码
  • 类图包括环境类(拥有状态的对象)、抽象状态类(封装与状态相关的行为)、具体状态类

    image-20240227000347541

18. 职责链模式

19. 享元模式

20. 解释器模式

21. 模板方法模式

22. 访问者模式


设计模式
https://2536184321.github.io/2023/09/24/设计模式/
作者
cky
发布于
2023年9月24日
许可协议