图说设计模式笔记#1

前言

之前自己也学习过设计模式,但是学了之后大部分设计模式没怎么在实际场景中使用过,导致知识点遗忘的差不多了。偶然间发现了me115/design_patterns 这个开源项目,趁此机会打算再系统得学习巩固一下设计模式知识。

图说设计模式:本书使用图形和代码结合的方式来解析设计模式

引用自图说设计模式

UML图形符号

关系 说明 符号说明 plantuml写法 图形
实现关系 继承抽象类 带空心三角箭头的虚线 <|…
泛化关系 继承非抽象类 带空心三角箭头的实线 <|--
组合关系 是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了 带实心菱形箭头的实线 *--
聚合关系 整体由部分构成,整体与部分不是强依赖,即使整体不存在了,部分依然存在 带空心菱形箭头的实线 o--
关联关系 描述不同类的对象之间的结构关系,是一种静态关系,与运行状态无关,是一种强关联的关系,默认不强调方向,表示对象间互相知道,如果A–>B 表示A知道B,B不知道A。在代码中通常以成员变量的形式实现。 实线 --
依赖关系 描述一个对象在运行期间会用到另一个对象的关系,与关联关系不同的是,它是一种临时性的关系,在运行间产生。在代码中表现为类构造方法及类方法的传入参数 带箭头的虚线 <…

设计模式按类型区分

  • 创建型模式
    • 简单工厂模式(Simple Factory)
    • 工厂方法模式(Factory Method)
    • 抽象工厂模式(Abstract Factory)
    • 建造者模式(Builder)
    • 原型模式(Prototype)
    • 单例模式(Singleton)
  • 结构型模式
    • 适配器模式(Adapter)
    • 桥接模式(Bridge)
    • 组合模式(Composite)
    • 装饰模式(Decorator)
    • 外观模式(Facade)
    • 享元模式(Flyweight)
    • 代理模式(Proxy)
  • 行为型模式
    • 职责链模式(Chain of Responsibility)
    • 命令模式(Command)
    • 解释器模式(Interpreter)
    • 迭代器模式(Iterator)
    • 中介者模式(Mediator)
    • 备忘录模式(Memento)
    • 观察者模式(Observer)
    • 状态模式(State)
    • 策略模式(Strategy)
    • 模板方法模式(Template Method)
    • 访问者模式(Visitor)

什么是创建型模式

创建型模式对类的实例化过程进行了抽象,将对象的创建和使用过程分离。使得外界只需要知道它们共同的接口,而不清楚具体的实线细节,使系统符合单一职责原则。

简单工厂模式

模式动机

提供一个方法,传入不同的参数来返回需要的对象。

模式定义

在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式结构

  • Factory:工厂角色,实现创建实例的逻辑
  • Product:抽象产品角色,工厂创建的所有对象的父类,负责描述所有实例的公共接口
  • ConcreteProduct:具体产品角色,最终创建的目标

在线编辑

时序图

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SimpleFactory {

public static Product createProduct(String type) {
Product product = null;
switch (type) {
case "A":
product = new ProductA();
break;
case "B":
product = new ProductB();
default:
break;
}
return product;
}

}

简单工厂模式优缺点

  • 优点
    • 工厂类包含判断逻辑,客户端没有创建产品的责任,只需要消费产品;通过此方式实现了对责任的分割
    • 客户端需要知道所创建具体产品的类名,只需要知道创建产品的参数即可,对于复杂类名,通过简单工厂模式可以减少使用者的记忆量
    • 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
  • 缺点
    • 工厂类集中了所有产品的创建逻辑,一旦出问题,整个系统都要受影响
    • 使用简单工厂模式会增加系统类的个数,在一定程度上增加了系统的复杂度和理解难度
    • 系统拓展困难,添加新产品就不得不修改工厂类,产品数量增多后可能会造成工厂逻辑变复杂,不利于系统拓展和维护
    • 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构

适用环境

  • 工厂类负责创建的对象比较少,逻辑不太复杂
  • 客户端只知道工厂类的参数,对创建对象的细节不关心

模式应用

  • java.text.DateFormat

    1
    2
    3
    4
    public final static DateFormat getDateInstance();
    public final static DateFormat getDateInstance(int style);
    public final static DateFormat getDateInstance(int style,Locale
    locale);
  • java加密技术

    1
    KeyGenerator keyGen=KeyGenerator.getInstance("DESede");

工厂方法模式

模式动机

创建过程交给专门的工厂子类去完成。每当出现一个新的产品,只需要为新产品创建一个具体的工厂类就可以,这一特点使得工厂方法模式具有超越简单工厂模式的优越性,更加符合开闭原则

模式定义

工厂方法模式又被称为工厂模式,也叫虚拟构造器模式或者多态模式。在工厂模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类负责生成具体的产品对象。

模式结构

  • Product:抽象产品
  • ConcreteProduct:具体产品
  • Factory:抽象工厂
  • ConcreteFactory:具体工厂

在线编辑

代码实现

父类工厂

1
2
3
public abstract class FactoryMethod {
public abstract Product createProduct();
}

工厂子类

1
2
3
4
5
6
public class ProductAFactory extends FactoryMethod {
@Override
public Product createProduct() {
return new ProductA();
}
}

使用

1
2
3
4
5
6
@Test
public void testFactoryMethod() {
FactoryMethod factory = new ProductAFactory();
Product product = factory.createProduct();
Assert.assertEquals(product.doSomething(), ProductA.class.getName());
}

模式分析

使用了面向对象的多态性。核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类,核心类仅仅负责子类必须实现的接口,不负责哪个产品被实例化的细节,使得允许系统在不修改工厂角色的情况下引进新产品

使用场景

工厂方法模式优缺点

  • 优点
    • 用户只需要关心所需产品对应的工厂,无须关心创建细节
    • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键,使得工厂子类可以自己决定创建何种产品,自己实现创建逻辑
    • 系统中加入新产品时,只要添加一个具体工厂和具体产品就可以,系统的扩展性就变得非常好,完全符合开闭原则
  • 缺点
    • 新增产品时需要编写新的具体产品类,也要提供与之对应的具体工厂类,系统中的类数量成对增加,一定程度上增加了系统的复杂度,以及增加系统编译运行的开销
    • 增加抽象层的定义,增加了系统的抽象性和理解难度

适用环境

  • 一个类不知道它所需要的对象的类,但要知道创建这个对象的具体工厂类
  • 一个类用过其子类来指定创建哪个对象
  • 将创建对象的任务委托个多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时在动态指定,可将具体工厂类名存储在配置文件或数据库中

模式应用

  • JDBC中的工厂方法

    1
    2
    3
    Connection conn=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=DB;user=sa;password=");
    Statement statement=conn.createStatement();
    ResultSet rs=statement.executeQuery("select * from UserInfo");

模式拓展

  • 在抽象工厂角色可以中定义多个工厂方法
  • 产品对象的重复使用:工厂对象将已经创建过的产品保存到一个集合中,然后根据客户对产品的请求,再对集合进行查询

图说设计模式笔记#1
https://blog.kedr.cc/posts/3935682145/
作者
zhuweitung
发布于
2022年6月25日
许可协议