工厂模式(Factory Pattern)

工厂模式是 Java 中最常用的设计模式之一
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象

介绍

意图:由工厂类创建一系列实现同一接口的对象
主要解决:主要解决接口选择的问题
何时使用:我们明确地计划不同条件下创建不同实例时
应用实例:
1.日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方
2.数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时
优点:
1.一个调用者想创建一个对象,只要知道其名称就可以了
2.扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
3.屏蔽产品的具体实现,调用者只关心产品的接口
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖

实现

1.Shape:同一接口
2.Circle/Square/Rectangle:实现Shape接口的类对象
3.ShapeFactory:通过getShape() -> 创建三种Shape
AB6B814A-0B09-4863-93D6-1E22D6B07FF8.jpg

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式是围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂

介绍

意图:工厂模式只能创建单一系列实例,抽象工厂用于扩展多系列实例
主要解决:主要解决接口选择的问题
何时使用:有多个系列实例需要由工厂创建
应用实例:
网易云换肤要把主页评论等各个模块实例都替换掉
优点:针对多系列实例,无需copy多个工厂
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的Creator 里加代码,又要在具体的里面加代码

实现

1.Shape/Color:同一接口
2.Circle/Square/Rectangle - Red/Green/Blue:实现同一接口的类对象
3.AbstractFactory:工厂的抽象父类
4.ShapeFactory/ColorFactory:继承AbstractFactory的工厂类对象,用于生产对象
5.FactoryProducer:用于生产AbstractFactory实体类

创建型模式 - 图2

单例模式(Singleton Pattern)

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
注意:

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须给所有其他对象提供这一实例

    介绍

    意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点
    主要解决:一个全局使用的类频繁地创建与销毁
    何时使用:当您想控制实例数目,节省系统资源的时候
    如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建
    应用实例:

  • Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行

  • 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件

优点:

  • 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)
  • 避免对资源的多重占用(比如写文件操作)

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

实现

我们将创建一个 SingleObject 类。SingleObject 类有它的私有构造函数和本身的一个静态实例。
SingleObject 类提供了一个静态方法,供外界获取它的静态实例。SingletonPatternDemo 类使用 SingleObject 类来获取 SingleObject 对象。
创建型模式 - 图3
1.饿汉式
1.基础类
是否 Lazy 初始化:
是否多线程安全:

  1. // 单例模式 - 核心私有构造方法[禁止额外初始化]
  2. private Example01() {
  3. }
  4. // 饿汉式
  5. private static final Example01 instance = new Example01();
  6. public static Example01 getInstance() {
  7. return instance;
  8. }

2.枚举类

  1. /**
  2. * 单例模式 - 枚举[无构造方法,防止反序列化]
  3. *
  4. * @author gdq
  5. * date 2021/3/15
  6. */
  7. public enum Example04 {
  8. // 单例变量
  9. INSTANCE;
  10. /**
  11. * 获取实例
  12. *
  13. * @return Example04 实例对象
  14. * @author gdq
  15. * @since 2021/3/15
  16. */
  17. public static Example04 getInstance() {
  18. return INSTANCE;
  19. }
  20. }

2.懒汉式
是否 Lazy 初始化:
是否多线程安全:
1.doubleCheck / volatile 多线程二次确认

  1. // 懒汉式 - doubleCheck / volatile屏蔽指令重排序
  2. private static volatile Example02 INSTANCE = null;
  3. public static Example02 getInstance() {
  4. if (INSTANCE == null) {
  5. synchronized (Example02.class) {
  6. if (INSTANCE == null) {
  7. INSTANCE = new Example02();
  8. }
  9. }
  10. }
  11. return INSTANCE;
  12. }

2.静态内部类 - jvm初始化

  1. // 静态内部类 - jvm控制类只有一次初始化
  2. private static class Example03Holder {
  3. private static final Example03 INSTANCE = new Example03();
  4. }
  5. /**
  6. * 获取实例
  7. *
  8. * @return Example03 实例对象
  9. * @author gdq
  10. * @since 2021/3/15
  11. */
  12. public static Example03 getInstance() {
  13. return Example03Holder.INSTANCE;
  14. }

建造者模式(Builder Pattern)

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
一个 Builder 类会一步一步构造最终的对象

介绍

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
何时使用:一些基本部件不会变,而其组合经常变化的时候
如何解决:拆分部件分别构造
应用实例: 1.lombok@builer 2.JAVA 中的 StringBuilder
优点:1.建造者独立,易扩展 2.便于控制细节风险
缺点:1.如内部变化复杂,会有很多的建造方法

实现

lombok.builder

  1. package org.gdq.learn.design.build;
  2. import lombok.ToString;
  3. /**
  4. * Example
  5. *
  6. * @author gdq
  7. * @since 2021/8/12
  8. */
  9. @ToString
  10. public class Example {
  11. // 组件1
  12. private String item1;
  13. // 组件2
  14. private int item2;
  15. // 组件3
  16. private double item3;
  17. // 组件4
  18. private boolean item4;
  19. public static ExampleBuilder builder() {
  20. return new ExampleBuilder();
  21. }
  22. // 建造者
  23. public static class ExampleBuilder {
  24. // 组件1
  25. private String item1;
  26. // 组件2
  27. private int item2;
  28. // 组件3
  29. private double item3;
  30. // 组件4
  31. private boolean item4;
  32. /**
  33. * 构造组件1
  34. *
  35. * @param item1 组件1
  36. * @return ExampleBuilder 返回建造者
  37. * @author gdq
  38. * @since 2021/8/12
  39. */
  40. public ExampleBuilder item1(String item1) {
  41. this.item1 = item1;
  42. return this;
  43. }
  44. /**
  45. * 构造组件2
  46. *
  47. * @param item2 组件2
  48. * @return ExampleBuilder 返回建造者
  49. * @author gdq
  50. * @since 2021/8/12
  51. */
  52. public ExampleBuilder item2(int item2) {
  53. this.item2 = item2;
  54. return this;
  55. }
  56. /**
  57. * 构造组件3
  58. *
  59. * @param item3 组件3
  60. * @return ExampleBuilder 返回建造者
  61. * @author gdq
  62. * @since 2021/8/12
  63. */
  64. public ExampleBuilder item3(double item3) {
  65. this.item3 = item3;
  66. return this;
  67. }
  68. /**
  69. * 构造组件4
  70. *
  71. * @param item4 组件4
  72. * @return ExampleBuilder 返回建造者
  73. * @author gdq
  74. * @since 2021/8/12
  75. */
  76. public ExampleBuilder item4(boolean item4) {
  77. this.item4 = item4;
  78. return this;
  79. }
  80. public Example build() {
  81. Example example = new Example();
  82. example.item1 = this.item1;
  83. example.item2 = this.item2;
  84. example.item3 = this.item3;
  85. example.item4 = this.item4;
  86. return example;
  87. }
  88. }
  89. }

原型模式(Prototype Pattern)

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆.当直接创建对象的代价比较大时,则采用这种模式.例如,一个对象需要在一个高代价的数据库操作之后被创建.我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用.

介绍

意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
主要解决:在运行期建立和删除原型
何时使用:1.当要实例化的类是在运行时刻指定时,例如,通过动态装载
如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例
关键代码: 1.实现克隆操作,在 JAVA 继承 Cloneable,重写 clone()
应用实例:1.JAVA 中的 Object clone() 方法
优点:1.性能提高 2.逃避构造函数的约束
缺点:1.配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候

实现

java.cloneable