# design_pattern **Repository Path**: th1nker/design_pattern ## Basic Information - **Project Name**: design_pattern - **Description**: Java的设计模式的学习 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-05-27 - **Last Updated**: 2023-05-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: Java, 设计模式 ## README # 设计模式 > author:thinker > > 单独下载本文件时需要绑定下载目录中的assets文件夹 ## 七大设计模式原则 ### 开闭原则 软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的 ### 依赖倒转(倒置)原则 程序要依赖于抽象接口,不要依赖于具体实现 要对抽象进行编程,不要对实现进行编程 ### 单一职责 就一个类而言,应该仅有一个引起它变化的原因,应该只有一个职责 ### 接口隔离原则 客户端不应该依赖它不需要的接口 一个类对另一个类的依赖应该建立在最小的接口上 ### 里氏代换原则 任何基类可以出现的地方,子类一定可以出现 只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为 对开闭原则的补充 ### 迪米特法则(最少知识原则) 一个类对于其他类知道的越少越好 一个对象应当对其他对象有尽可能少的了解 只和朋友通信,不和陌生人说话 ### 合成复用原则 软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。 ## 创建型 ### 简单工厂 #### 定义 由一个工厂对象决定创建出哪一种产品类的实例 不属于GOF23种设计模式 #### 适用场景 - 工厂类负责创建的对象比较少 - 客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心 #### 优点 - 只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节 #### 缺点 - 工厂类的职责相对过重,增加新的产品,需要修改工厂类的判断逻辑,违背开闭原则 #### 代码实例 ##### 抽象产品Video ```java package cloud.th1nker.designpattern.pattern.creational.simplefactory; /** * @author Thinker * @create 2023/5/28 12:05 * @since */ public abstract class Video { public abstract void produce(); } ``` ##### 具体产品JavaVideo ```java package cloud.th1nker.designpattern.pattern.creational.simplefactory; /** * @author Thinker * @create 2023/5/28 12:05 * @since */ public class JavaVideo extends Video { public void produce() { System.out.println("录制java课程视频"); } } ``` ##### 具体产品PythonVideo ```java package cloud.th1nker.designpattern.pattern.creational.simplefactory; /** * @author Thinker * @create 2023/5/28 12:05 * @since */ public class PythonVideo extends Video { public void produce() { System.out.println("录制python课程视频"); } } ``` ##### 工厂类VideoFactory ```java package cloud.th1nker.designpattern.pattern.creational.simplefactory; /** * @author Thinker * @create 2023/5/28 12:07 * @since */ public class VideoFactory { public Video getVideo(Class c) { Video video; try { video = (Video) Class.forName(c.getName()).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { throw new RuntimeException(e); } return video; } public Video getVideo(String type) { if ("java".equalsIgnoreCase(type)) { return new JavaVideo(); } else if ("python".equalsIgnoreCase(type)) { return new PythonVideo(); } else { return null; } } } ``` #### UML图 ![简单工厂UML](./assets/简单工厂UML.png) ### 工厂方法模式 #### 定义 定义一个创建对象的接口 但让实现这个接口的类来决定实例化哪个类 工厂方法让类的实例化推迟到子类中进行 #### 适用场景 - 创建对象需要大量重复的代码 - 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节 - 一个类通过其子类来指定创建哪个对象 #### 优点 - 用户只需要关心产品对应的工厂,无需关心创建细节 - 加入新产品复合开闭原则,提高可扩展性 #### 缺点 - 类的个数容易过多,增加复杂度 - 增加了系统的抽象性和理解难度 #### 代码实例 ##### 抽象产品Video ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:05 * @since */ public abstract class Video { public abstract void produce(); } ``` ##### 抽象工厂VideoFactory ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:07 * @since */ public abstract class VideoFactory { public abstract Video getVideo(); } ``` ##### 具体产品JavaVideo ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:05 */ public class JavaVideo extends Video { public void produce() { System.out.println("录制java课程视频"); } } ``` ##### 具体产品工厂JavaVideoFactory ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:46 */ public class JavaVideoFactory extends VideoFactory { public Video getVideo() { return new JavaVideo(); } } ``` ##### 具体产品PythonVideo ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:05 */ public class PythonVideo extends Video { public void produce() { System.out.println("录制python课程视频"); } } ``` ##### 具体产品工厂PythonVideoFactory ```java package cloud.th1nker.designpattern.pattern.creational.factorymethod; /** * @author Thinker * @create 2023/5/28 12:47 */ public class PythonVideoFactory extends VideoFactory { public Video getVideo() { return new PythonVideo(); } } ``` #### UML图 ![工厂方法UML](./assets/工厂方法UML.png) ### 抽象工厂模式 #### 定义 提供一个创建一系列相关或者相互依赖对象的接口 无须指定他们具体的类 #### 适用场景 - 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节 - 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码 - 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现 #### 优点 - 具体产品在应用层隔离,无需关系创建细节 - 将一个系列的产品族统一到一起创建 #### 缺点 - 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口 - 增加了系统的抽象性和理解难度 #### 产品族和产品结构 ![产品族和产品结构](./assets/产品族和产品结构.png) #### 代码实例 ##### 抽象产品工厂CourseFactory ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:41 */ public interface CourseFactory { Video getVideo(); Article getArticle(); } ``` ##### 抽象产品Video ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:42 */ public abstract class Video { public abstract void produce(); } ``` ##### 抽象产品Article ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:41 */ public abstract class Article { public abstract void produce(); } ``` ##### 具体产品JavaArticle ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:43 */ public class JavaArticle extends Article { @Override public void produce() { System.out.println("创建java手记"); } } ``` ##### 具体产品PythonArticle ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:44 */ public class PythonArticle extends Article { @Override public void produce() { System.out.println("创建python手记"); } } ``` ##### 具体产品JavaVideo ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:43 */ public class JavaVideo extends Video { @Override public void produce() { System.out.println("录制java课程视频"); } } ``` ##### 具体产品PythonVideo ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:44 */ public class PythonVideo extends Video { @Override public void produce() { System.out.println("录制python视频"); } } ``` ##### 具体工厂JavaCourseFactory ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:43 */ public class JavaCourseFactory implements CourseFactory { @Override public Video getVideo() { return new JavaVideo(); } @Override public Article getArticle() { return new JavaArticle(); } } ``` ##### 具体工厂PythonCourseFactory ```java package cloud.th1nker.designpattern.pattern.creational.abstractfactory; /** * @author Thinker * @create 2023/5/28 14:45 */ public class PythonCourseFactory implements CourseFactory { @Override public Video getVideo() { return new PythonVideo(); } @Override public Article getArticle() { return new PythonArticle(); } } ``` #### UML图 ![抽象工厂UML](./assets/抽象工厂UML.png) ### 单例模式 #### 定义 保证一个类仅有一个实例,并提供一个全局访问点 #### 适用场景 - 想确保任何情况下都绝对只有一个实例 #### 优点 - 在内存里只有一个实例,减少了内存开销 - 可以避免对资源的多重占用 - 设置全局访问点,严格控制访问 #### 缺点 - 没有接口,扩展困难 #### 重点 - 私有构造器 - 线程安全 - 延迟加载 - 序列化和反序列化安全 - 反射 #### 代码实例 ##### 饿汉式单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; import java.io.Serializable; /** * @author Thinker * @create 2023/5/28 16:07 */ public class HungrySingleton implements Serializable { private static final HungrySingleton instance; static { instance = new HungrySingleton(); } private HungrySingleton() { if (instance != null) { throw new RuntimeException("单例构造器禁止反射调用"); } } public static HungrySingleton getInstance() { return instance; } /** * 解决序列化问题 */ private Object readResolve() { return instance; } } ``` ##### 懒汉式单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; /** * @author Thinker * @create 2023/5/28 15:40 */ public class LazySingleton { private static LazySingleton lazySingleton; private LazySingleton() { } public synchronized static LazySingleton getInstance() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; } } ``` ##### 静态内部类单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; /** * @author Thinker * @create 2023/5/28 16:01 */ public class StaticInnerClassSingleton { private StaticInnerClassSingleton() { if (InnerClass.singleton != null) { throw new RuntimeException("单例构造器禁止反射调用"); } } public static StaticInnerClassSingleton getInstance() { return InnerClass.singleton; } private static class InnerClass { private static StaticInnerClassSingleton singleton = new StaticInnerClassSingleton(); } } ``` ##### 双重检查懒汉式单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; /** * @author Thinker * @create 2023/5/28 15:53 */ public class LazyDoubleCheckSingleton { // 使用volatile,保证内存可见性 private static volatile LazyDoubleCheckSingleton lazyDoubleCheckSingleton; private LazyDoubleCheckSingleton() { } public static LazyDoubleCheckSingleton getInstance() { if (lazyDoubleCheckSingleton == null) { synchronized (LazyDoubleCheckSingleton.class) { if (lazyDoubleCheckSingleton == null) { lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton(); // 1.分配内存 // 2.初始化对象 // 3.设置lazyDoubleCheckSingleton指向该内存地址 // 可能会有指令重排序 } } } return lazyDoubleCheckSingleton; } } ``` ##### 枚举单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; /** * @author Thinker * @create 2023/5/28 16:46 */ public enum EnumInstance { INSTANCE; private Object data; public static EnumInstance getInstance() { return INSTANCE; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } } ``` ##### 线程单例 ```java package cloud.th1nker.designpattern.pattern.creational.singleton; /** * @author Thinker * @create 2023/5/28 17:39 */ public class ThreadLocalInstance { private static final ThreadLocal threadLocalInstance = ThreadLocal.withInitial(ThreadLocalInstance::new); public ThreadLocalInstance getInstance() { return threadLocalInstance.get(); } } ``` ### 建造者模式 #### 定义 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 用户只需指定需要建造的类型就可以得到他们,建造过程及细节不需要知道 #### 适用场景 - 如果一个对象有非常复杂的内部结构(很多属性) - 想把复杂对象的创建和使用分离 #### 优点 - 封装性好,创建和使用分离 - 扩展性好、建造类之间独立、一定程度解耦 #### 缺点 - 产生多余的Builder对象 - 产品内部发生变化,建造者都要修改,成本较大 #### 代码实例 ##### v1 ###### 产品类Course ```java package cloud.th1nker.designpattern.pattern.creational.builder.v1; /** * @author Thinker * @create 2023/5/28 15:03 */ public class Course { private String courseName; private String coursePPT; private String courseVideo; private String courseArticle; private String courseQA; // getter setter toString省略 } ``` ###### 抽象建造者CourseBuilder ```java package cloud.th1nker.designpattern.pattern.creational.builder.v1; /** * @author Thinker * @create 2023/5/28 15:04 */ public abstract class CourseBuilder { public abstract void buildCourseName(String name); public abstract void buildCoursePPT(String ppt); public abstract void buildCourseVideo(String video); public abstract void buildCourseArticle(String article); public abstract void buildCourseQA(String qa); public abstract Course makeCourse(); } ``` ###### 具体建造者CourseActualBuilder ```java package cloud.th1nker.designpattern.pattern.creational.builder.v1; /** * @author Thinker * @create 2023/5/28 15:06 */ public class CourseActualBuilder extends CourseBuilder { private final Course course = new Course(); @Override public void buildCourseName(String name) { course.setCourseName(name); } @Override public void buildCoursePPT(String ppt) { course.setCoursePPT(ppt); } @Override public void buildCourseVideo(String video) { course.setCourseVideo(video); } @Override public void buildCourseArticle(String article) { course.setCourseArticle(article); } @Override public void buildCourseQA(String qa) { course.setCourseQA(qa); } @Override public Course makeCourse() { return course; } } ``` ###### 指导者类Coach(非必须) ```java package cloud.th1nker.designpattern.pattern.creational.builder.v1; /** * @author Thinker * @create 2023/5/28 15:08 */ public class Coach { private CourseBuilder courseBuilder; public void setCourseBuilder(CourseBuilder courseBuilder) { this.courseBuilder = courseBuilder; } public Course makeCourse(String name, String ppt, String video, String article, String qa) { courseBuilder.buildCourseName(name); courseBuilder.buildCoursePPT(ppt); courseBuilder.buildCourseArticle(article); courseBuilder.buildCourseVideo(video); courseBuilder.buildCourseQA(qa); return courseBuilder.makeCourse(); } } ``` ###### UML图 ![建造者模式v1](./assets/建造者模式v1.png) ##### v2(内部类) ###### 产品Course类 ```java package cloud.th1nker.designpattern.pattern.creational.builder.v2; /** * @author Thinker * @create 2023/5/28 15:15 */ public class Course { private String courseName; private String coursePPT; private String courseVideo; private String courseArticle; private String courseQA; public Course(CourseBuilder courseBuilder) { this.courseName = courseBuilder.courseName; this.coursePPT = courseBuilder.coursePPT; this.courseVideo = courseBuilder.courseVideo; this.courseArticle = courseBuilder.courseArticle; this.courseQA = courseBuilder.courseQA; } // setter getter toString省略 public static class CourseBuilder { private String courseName; private String coursePPT; private String courseVideo; private String courseArticle; private String courseQA; public CourseBuilder buildCourseName(String name) { this.courseName = name; return this; } public CourseBuilder buildCoursePPT(String coursePPT) { this.coursePPT = coursePPT; return this; } public CourseBuilder buildCourseVideo(String courseVideo) { this.courseVideo = courseVideo; return this; } public CourseBuilder buildCourseArticle(String courseArticle) { this.courseArticle = courseArticle; return this; } public CourseBuilder buildCourseQA(String courseQA) { this.courseQA = courseQA; return this; } public Course build() { return new Course(this); } } } ``` ###### UML图 ![建造者模式v2](./assets/建造者模式v2.png) ### 原型模式 #### 定义 原型实例指定创建对象的类,并通过拷贝这些原型创建新的对象 不需要知道任何创建的细节,**不调用构造函数** #### 适用场景 - 类初始化消耗较多资源 - new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等) - 构造函数比较复杂 - 循环体中生产大量对象时 #### 优点 - 原型模式性能比直接new一个对象性能高 - 简化创建过程 #### 缺点 - 必须配备克隆方法 - 对克隆复杂对象或克隆出的对象进行复杂改造时,容器引入风险 - 深拷贝、浅拷贝要运用得当 #### 扩展 - 深拷贝 - 浅拷贝 #### 代码实例 ##### 浅拷贝 ```java package cloud.th1nker.designpattern.pattern.creational.prototype; /** * @author Thinker * @create 2023/5/28 17:55 */ public class Mail implements Cloneable { private String name; private String emailAddress; private String content; public Mail() { } @Override protected Object clone() throws CloneNotSupportedException { System.out.println("clone mail object"); return super.clone(); } // setter getter toString } ``` ##### 深拷贝 ```java package cloud.th1nker.designpattern.pattern.creational.prototype.clone; import java.util.Date; /** * @author Thinker * @create 2023/5/28 18:07 */ public class Pig { private String name; private Date birthDay; public Pig() { } public Pig(String name, Date birthDay) { this.name = name; this.birthDay = birthDay; } @Override protected Object clone() throws CloneNotSupportedException { Pig clone = (Pig) super.clone(); // 执行深克隆 clone.setBirthDay((Date) clone.getBirthDay().clone()); return clone; } // setter getter toString } ``` ## 结构型 ### 桥接模式 ### 适配器模式 ### 组合模式 ### 装饰器模式 ### 外观模式(门面模式) ### 享元模式 ### 代理模式 ## 行为型 ### 策略模式 ### 模板方法模式 ### 观察者模式 ### 备忘录模式 ### 迭代器模式 ### 命名模式 ### 解释器模式 ### 中介者模式 #### 定义 定义一个封装一组对象如何交互的对象 通过使对象明确地相互引用来促进松耦合,并允许独立地改变他们的交互 #### 适用场景 - 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解 - 交互的公共行为,如果需要改变行为可以增加新的中介者类 #### 优点 - 将一对多转化成了一对一,降低程序复杂度 - 类之间解耦 #### 缺点 - 中介者过多,导致系统复杂 ### 责任链模式(职责链模式) #### 定义 为请求创建一个接收此次请求对象的链 #### 适用场景 - 一个请求的处理需要多个对象当中的一个或几个协作处理 #### 优点 - 请求的发送者和接收者(处理者)解耦 - 责任链可以动态组合 #### 缺点 - 责任链太长或者处理时间太长,影响性能 - 责任链有可能过多 ### 访问者模式 #### 定义 封装作用于某数据结构(如List/Set/Map等)中的各元素的操作 可以在不改变各元素的类的前提下,定义作用于这些元素的操作 #### 适用场景 - 一个数据结构(List/Set/Map等)包含很多类型对象 - 数据结构和数据操作分离 #### 优点 - 增加新的操作很容易,即增加一个新的访问者 #### 缺点 - 增加新的数据结构困难 - 具体元素变更比较麻烦 ### 状态模式 #### 定义 允许一个对象在其内部状态改变时,改变它的行为 #### 适用场景 - 一个对象存在多个状态(不同状态下行为不同),且状态可以互相转换 #### 优点 - 将不同的状态隔离 - 把各种状态的转换逻辑,分布到State的子类中,减少互相依赖 - 增加新的状态非常简单 #### 缺点 - 状态多的业务场景导致类的数目增加,系统变复杂