持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
分类
设计模式分为:创建型模式、结构型模型、行为模型
- 创建型模式:用于创建对象的设计模式。一般可以简化用户创建对象的过程。其次可以降低耦合度,用户不需要关心对象具体的创建过程。
- 单例模式⭐️、原型模型、抽象工厂模式、建造者模式、工厂方法模式⭐️
- 结构型模型:组织对象之间的结构,使其易于扩展。
- 代理模式⭐️、适配器模式⭐️、桥接模式、装饰器模式、外观模式、享元模式、组合模式
- 行为模型:主要用于决定对象如何做出行为。
- 模板方法模式⭐️、策略模式、命令模式、责任链、状态模式、观察者模式⭐️、中介者模式、迭代器模式、访问者模式、备忘录模式、解释器模式
六大原则
- 开放封闭原则:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化。即对扩展开放,对修改封闭,每个类都有自己负责的职责。
- 里氏替换原则(Liskov Substitution Principle):子类可以扩展父类的功能,但不能改变原有父类的功能,不能破坏继承关系的体系。
- 依赖倒置原则(Dependence Inversion Principle):面向接口编程,要求在编码中传递参数时,尽量引用高层次的抽象层类。
- 接口隔离原则(interface segregation principle):使用多个隔离的接口,比使用单个接口要好,降低耦合。
- 迪米特法则(最少知道原则)(Demeter Principle):一个类对于其他类知道的越少越好,尽量降低类之间的耦合。应该尽量减少对象之间的交互,如果两个对象不必直接通信,那么这两个对象就不应该发生任何直接的相互作用,如果其中一个对象需要调用另外一个对象的某个方法时,可以通过第三者转发这个调用,就是通过引入一个合理的第三者来降低先有对象之间的耦合度,比如引入MQ消息中间件。
- 单一职责原则(Principle of single responsibility):一个方法/一个类只负责一件职责,各个职责的程序代码改动,不影响其他程序。降低类之间的耦合,提高可维护性和可扩展性。
单例模式⭐️
单例模式需要保证一个类只有一个实例,并提供一个全局访问的方法调用这个实例。

单例模式提供了两种方式,懒汉模式和饿汉模式
- 懒汉模式:首次使用单例实例的时候创建,之后使用时再判断单例实例是否已创建,如果没有则创建实例。在多线程使用中,需要考虑线程安全问题。
- 饿汉模式:在该类初始化的时候就创建实例对象,线程是安全的。
/**
* 懒汉模式:首次使用单例实例的时候创建,之后使用时再判断单例实例是否已创建,如果没有则创建实例。
*/
class LazySingleton {
private static LazySingleton instance = null;
private Singleton() {
}
// 饿汉模式需要考虑线程安全问题,因为在使用时创建实例,可能有多个线程同时在调用。以下几种实现
// 1.效率最高,线程安全
public static LazySingleton getInstance() {
// 如果对象为空才进入同步方法块,否则返回实例对象
if (instance == null) {
synchronized (LazySingleton.class) {
// 确保线程安全
if (instance == null)
instance = new LazySingleton();
}
}
return instance;
}
// 2.静态synchronized方法 线程安全
public static synchronized LazySingleton getInstance2() {
if (instance == null)
instance = new LazySingleton();
return instance;
}
// 3.synchronized class同步块(每次调用都进入同步块) 线程安全
public static LazySingleton getInstance3() {
synchronized (LazySingleton.class) {
if (instance == null)
instance = new LazySingleton();
}
return instance;
}
// 4.不加同步锁 线程不安全
public static LazySingleton getInstance4() {
if (instance == null)
instance = new LazySingleton();
return instance;
}
}
/**
* 饿汉模式:在该类初始化的时候就创建实例对象,线程是安全的。
*/
class HungrySingleton {
// 不管有没有需求,类初始的时候就创建实例对象
private static final HungrySingleton instance = new HungrySingleton();
private Singleton() {
}
public static final HungrySingleton getInstance() {
return instance;
}
}
注意:
- 单例模式中,不能使用反射模式创建单例,反射会创建一个新的实例对象。
- 懒汉模式,需要考虑线程安全问题。
- 单例模式中,构造方法时私有的,不能被继承。
工厂模式
工厂模式中由工厂提供创建对象的接口来代替new创建对象实例,实现调用者与创建者的分离,降低程序耦合。工厂模式又分为简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式
简单工厂模式相当于现实中的一个工厂,我们可以通过工厂生产产品,这里是通过工厂创建对象实例。用户只需要知道对象的名称,工厂就可以返回对应名称的对象实例。

工厂方法模式
在简单工厂模式中,存在这样一个缺点,如果需要增加工厂的产品,那么就需要修改工厂类方法,一个工厂生产多种产品。工厂方法模式就是一个工厂只生产一种产品,后期扩展产品需要创建新工厂。

抽象工厂模式
就工厂模式而言,一个工厂只能生产一种产品,如果要求一个工厂同时兼生产多种产品,这种需求就不能满足。
在抽象工厂模式中,抽象工厂类中定义了多种产品,即定义其子类应该生产哪几种产品。但后期抽象工厂再增加产品时,需要对所有具体工厂进行修改。

区别
- 简单工厂:所有的产品都由一个工厂生产。如果后期需要增加产品,就需要修改工厂代码。
- 工厂方法:可以有多个工厂,但一个工厂只生产一种产品。如果后期需要增加产品,那就需要增加工厂类。
- 抽象工厂:可以有多个工厂,每个工厂可以生产多类产品。如果后期需要增加产品,那么就需要在抽象工厂里加抽象方法,然后修改所有的子类。
代理模式
通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。
在Spring AOP中,就是应用了代理模式。代理模式实现方法,通常有静态代理和动态代理两种方式。
- 静态代理:在程序运行前就已经存在代理类,可以是开发者自己便携的代理类或AspectJ等工具生成的代理类。
- 动态代理:在程序运行时,利用 JDK 的反射机制,动态地在内存中构建代理对象。如Spring AOP
