23 个经典设计模式
0.序
类型分类
| 创造型(5 个) | 结构型(7 个) | 行为型(11 个) |
|---|---|---|
| 抽象工厂(Abstract Factory) | 适配器(Adapter) | 职责链(Chain of Responsibility) |
| 建造者(Builder) | 桥接(Bridge) | 命令(Command) |
| 原型(Prototype) | 组合(Composite) | 解释器(Interpreter) |
| 单例(Singleton) | 装饰(Decorator) | 迭代器(Iterator) |
| 工厂方法(Factory Method) | 外观(Facade) | 中介者(Mediator) |
| 享元(Flyweight) | 备忘录(Memento) | |
| 代理(Proxy) | 观察者(Observer) | |
| 状态(State) | ||
| 策略(Strategy) | ||
| 模板方法(Template Method) | ||
| 访问者(Visitor) |
类图介绍
类图分为三层,第一层显示类名称,第二层类的属性字段,第三层方法。
- ”+“:public
- ”-” :private
- ”#“:protect
关联(Association)
- 长期拥有
- 作为类的属性(成员变量)存在
依赖(Dependency)
- 用一下就走
- 只出现在方法参数、返回值、局部变量、临时创建对象中
聚合(Aggregation)
-
表示弱拥有关系(has-a,但松散的)
-
部分可以独立存在
-
UML 符号:空心菱形(
o--) -
生命周期:整体销毁不影响部分
-
例子:
班级(Class)聚合学生(Student)- 学生可以存在于多个班级或独立存在
- 删除班级,学生仍然存在
合成(Composition)
-
表示强拥有关系(包含/组合,强依赖)
-
部分不能独立存在
-
UML 符号:实心菱形(
*--) -
生命周期:整体销毁,部分也会销毁
-
例子:
汽车(Car)组合发动机(Engine)- 发动机完全属于这辆车
- 汽车销毁,发动机也不存在
classDiagram
direction TB
%% 接口(stereotype 写在类体内)
class IFlyable {
<<interface>>
+fly()
}
%% 类
class Animal {
+eat()
}
class Dog {
+bark()
}
class Bird {
+chirp()
}
class WingedDog {
+bark()
+fly()
}
class Zoo {
-animals : Animal[]
+addAnimal(a : Animal)
}
class Cage {
-animal : Animal
}
class Vet {
+treat(a : Animal)
}
class Engine {
+start()
}
class Car {
-engine : Engine
+drive()
}
%% 继承
Animal <|-- Dog:继承父类
Animal <|-- Bird:继承父类
Animal <|-- WingedDog:继承父类
%% 实现
Bird ..|> IFlyable: 实现接口
WingedDog ..|> IFlyable: 实现接口
%% 关联
Zoo --> Animal : 关联关系:包含
Zoo --> Cage : 关联关系:容纳
%% 聚合(空心菱形)
Cage o-- Animal : 聚合关系:关着,弱拥有
%% 组合(实心菱形)
Car *-- Engine : 组合关系:拥有,强拥有
%% 依赖(虚线)
Vet ..> Animal : 依赖关系:治疗
设计模式原则
- 开闭原则(OCP)——设计模式之王 (对扩展开放,对修改关闭)
-
新需求 → 加代码
-
而不是 → 改老代码
📌典型体现:
- 策略模式
- 装饰器模式
- 工厂方法模式
- 单一职责原则(SRP)(一个类只负责一件事)
- 修改影响面小
- 代码更容易复用
📌 典型体现:
- 装饰器模式(日志 / 鉴权 / 缓存各自独立)
- 责任链模式
- 依赖倒置原则(DIP)(依赖抽象,而不是依赖具体实现)
// 好
List list;
// 坏
ArrayList list;
通过抽象 + 多态来反转依赖方向
📌 典型体现:
- 策略模式
- 工厂模式
- 模板方法模式
- 里氏替换原则(LSP)(子类必须能替换父类而不影响程序正确性) 父类能干的,子类一定能干;父类承诺的,子类不能反悔。
📌 违反示例:
-
子类抛出父类没声明的异常
-
class Bird { void fly() { System.out.println("鸟在飞"); } } class Ostrich extends Bird { @Override void fly() { throw new UnsupportedOperationException("鸵鸟不会飞"); } }
-
-
子类改变父类语义
-
// 父类中方法 void getTotalPrice(double amount){ retrun amount; } // 子类重写方法 void getTotalPrice(double amount) { return amount * 0.8; }
-
-
子类 不能加强前置条件
-
// 父类中方法 void pay(double amount); // 子类重写方法 void pay(double amount) { if (amount < 1000) throw ... }
-
📌 强烈相关模式:
- 装饰器
- 代理
- 策略
- 接口隔离原则(ISP)(不强迫类实现它不需要的方法)
// ❌
interface Animal {
fly();
swim();
run();
}
// ✅
interface Flyable {}
interface Swimmable {}
📌典型体现:
- 适配器模式
- 策略模式
- 迪米特法则(最少知识原则)(尽量让一个类少认识其他类)
📌典型体现:
- 外观模式
- 中介者模式
- 代理模式
1.简单工厂
简单工厂模式(Simple Factory Pattern) → 创建型设计模式
简单工厂模式通过一个工厂类根据参数的不同创建不同类型的对象。 客户端只需知道工厂类和产品接口,而不需要关心具体产品类的实现。(不属于经典的设计模式)
| 项目 | 内容 |
|---|---|
| 解决问题 | 解决客户端与具体产品类耦合,集中管理对象创建逻辑,提高可维护性 |
| 核心结构 | 1. 工厂类(Factory):负责创建对象 2. 抽象产品类(Product):定义公共接口 3. 具体产品类(ConcreteProduct):实现接口 4. 客户端(Client):通过工厂获取对象 |
| 应用场景 | 1. 对象创建逻辑复杂或变化不频繁 2. 客户端只需接口,不关心具体实现 3. 产品种类有限 4. 业务逻辑和对象创建分离 |
| 优点 | - 客户端和具体类解耦 - 集中管理对象创建逻辑,方便维护 |
| 缺点 | - 工厂类集中过多逻辑,易臃肿 - 违反开闭原则,新增产品需修改工厂类 |
public abstract class Operation {
public double getResult(double numberA,double numberB){
return 0d;
}
}
public class Add extends Operation{
@Override
public double getResult(double numberA,double numberB){
return numberA + numberB;
}
}
public class Sub extends Operation{
@Override
public double getResult(double numberA,double numberB){
return numberA - numberB;
}
}
public class OperationFactory{
public static Operation createOperate(String operate){
Operation oper = null;
swith(oper){
case "+":
oper = new Add();
break;
case "-":
oper = new Sub();
break;
}
return oper;
}
}
public class Client(){
public static void main(String[] args){
String strOperate = "+";
double numberA = 1;
double numberB = 2;
Operation oper = OperationFactory.createOperate(strOperate);
double result = oper.getResult(numberA,numberB)
}
}
UML类图
classDiagram
class Operation {
<<abstract>>
+getResult(numberA: double, numberB: double): double
}
class Add {
+getResult(numberA: double, numberB: double): double
}
class Sub {
+getResult(numberA: double, numberB: double): double
}
class OperationFactory {
+createOperate(operate: String): Operation
}
Operation <|-- Add
Operation <|-- Sub
OperationFactory ..> Operation
2.策略模式
策略模式(Strategy Pattern) → 行为型设计模式
策略模式定义了一系列算法,把每一个算法封装起来,并使它们可以互相替换。 这样,算法的变化不会影响使用算法的客户代码,客户端可以在运行时选择不同的策略。
| 项目 | 内容 |
|---|---|
| 解决问题 | 解决不同算法或行为在客户端硬编码的问题,通过封装算法实现解耦和可替换性 |
| 核心结构 | 1. 策略接口(Strategy):定义公共算法接口 2. 具体策略类(ConcreteStrategy):实现不同算法 3. 环境类(Context):持有策略接口引用,根据需要调用不同策略 4. 客户端(Client):通过环境类设置或切换策略 |
| 应用场景 | 1. 系统中有多种算法或行为,需要动态选择 2. 避免使用大量条件语句(if-else 或 switch) 3. 算法稳定且独立,频繁变化 4. 提高代码扩展性和可维护性 |
| 优点 | - 算法封装,策略之间独立,符合开闭原则 - 避免大量条件判断,减少耦合- 可动态切换算法 |
| 缺点 | - 会增加策略类数量,系统复杂度提高 - 客户端必须理解不同策略的差异才能选择合适策略 |
public abstract class Strategy{
public abstract void algorithmInterface();
}
public ConcreteStrategyA extends Strategy{
@Override
public void algorithmInterface(){
System.out.println("算法A实现");
}
}
public ConcreteStrategyB extends Strategy{
@Override
public void algorithmInterface(){
System.out.println("算法B实现");
}
}
public ConcreteStrategyC extends Strategy{
@Override
public void algorithmInterface(){
System.out.println("算法C实现");
}
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public void contextInterface(){
strategy.algorithmInterface();
}
}
public class Client(){
public static void main(String[] args){
Context context;
context = new Context(new ConcreteStrategyA());
context.contextInterface();
}
}
UML类图
classDiagram
class Strategy {
<<abstract>>
+algorithmInterface(): void
}
class ConcreteStrategyA {
+algorithmInterface(): void
}
class ConcreteStrategyB {
+algorithmInterface(): void
}
class ConcreteStrategyC {
+algorithmInterface(): void
}
class Context {
-strategy: Strategy
+Context(strategy: Strategy)
+contextInterface(): void
}
Strategy <|-- ConcreteStrategyA
Strategy <|-- ConcreteStrategyB
Strategy <|-- ConcreteStrategyC
Context --> Strategy
3.装饰模式
装饰器模式(Decorator Pattern) → 结构型设计模式
装饰器模式是结构型设计模式,允许在不修改原始对象代码的前提下,动态地给对象添加新的职责或行为。 它通过组合和多态实现功能增强,使对象可以在运行时被“包装”成不同的功能层。
- 把“变化的东西”抽离出去
- 让增强“可插拔”
- 开闭原则(真正落地)
| 项目 | 内容 |
|---|---|
| 解决问题 | 在不修改原有类的情况下,为对象动态添加额外功能,解决继承扩展功能带来的类爆炸问题 |
| 核心结构 | 1. 抽象组件(Component):定义对象接口 2. 具体组件(ConcreteComponent):实现基础功能 3. 装饰抽象类(Decorator):持有组件引用,实现接口,可调用组件方法 4. 具体装饰类(ConcreteDecorator):在调用组件基础功能上增加新行为 |
| 应用场景 | 1. 需要在运行时动态给对象添加功能 2. 功能扩展数量多,如果用继承会产生大量子类3. 希望对对象功能进行有选择的叠加 |
| 优点 | - 动态扩展对象功能,比继承更灵活- 遵循开闭原则 - 可以通过组合不同装饰器叠加功能 |
| 缺点 | - 多层装饰会导致系统设计复杂,调试困难 - 每个装饰类都要实现组件接口,增加类数量 |
public interface Component {
void operation();
}
public class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("执行核心业务逻辑");
}
}
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation(); // 默认放行
}
}
public class LogDecorator extends Decorator {
public LogDecorator(Component component) {
super(component);
}
@Override
public void operation() {
System.out.println("【日志】开始");
super.operation();
System.out.println("【日志】结束");
}
}
public class AuthDecorator extends Decorator {
public AuthDecorator(Component component) {
super(component);
}
@Override
public void operation() {
if (!checkAuth()) {
throw new RuntimeException("无权限访问");
}
System.out.println("【鉴权】通过");
super.operation();
}
private boolean checkAuth() {
return true;
}
}
public class Client {
public static void main(String[] args) {
Component component =
new LogDecorator(
new AuthDecorator(
new ConcreteComponent()
)
);
component.operation();
}
}
UML类图
classDiagram
%% 顶层接口
class Component {
<<interface>>
+operation()
}
%% 具体组件
class ConcreteComponent {
+operation()
}
ConcreteComponent ..|> Component
%% 抽象装饰器
class Decorator {
-component: Component
+Decorator(component: Component)
+operation()
}
Decorator ..|> Component
Decorator --> Component : "has-a"
%% 具体装饰器
class LogDecorator {
+LogDecorator(component: Component)
+operation()
}
class AuthDecorator {
+AuthDecorator(component: Component)
+operation()
}
LogDecorator --|> Decorator
AuthDecorator --|> Decorator
4.代理模式
代理模式(Proxy Pattern) → 结构型设计模式
代理模式为其他对象提供一种代理以控制对这个对象的访问。 代理对象与真实对象实现相同接口,通过中间层在访问前后添加控制逻辑,而客户端无需感知真实对象的存在。
| 项目 | 内容 |
|---|---|
| 解决问题 | 控制对某个对象的访问,可在不修改原对象的情况下添加功能,如权限控制、延迟加载、缓存等 |
| 核心结构 | 1. 抽象主题(Subject):定义真实对象和代理对象的公共接口 2. 真实主题(RealSubject):实现具体业务逻辑 3. 代理类(Proxy):持有真实对象引用,在调用真实对象前后加额外功能 4. 客户端(Client):通过代理对象访问真实对象 |
| 应用场景 | 1. 需要对对象访问进行控制(权限、审计、日志等) 2. 对象创建开销大,使用代理延迟加载(虚代理) 3. 为对象添加额外功能而不改变原类(装饰、保护) 4. 远程代理:客户端操作本地代理,代理转发请求到远程对象 |
| 优点 | - 控制对象访问,可在不修改对象情况下增强功能 - 可以隐藏对象具体实现细节- 可以灵活扩展对象功能 |
| 缺点 | - 增加系统类数量,增加设计复杂度 - 多层代理可能导致调用层层嵌套,调试困难 |
public interface Subject {
void request();
}
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("执行真实业务逻辑");
}
}
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
postRequest();
}
private void preRequest() {
System.out.println("代理:前置处理");
}
private void postRequest() {
System.out.println("代理:后置处理");
}
}
public class Client {
public static void main(String[] args) {
Subject subject = new Proxy();
subject.request();
}
}
UML类图
classDiagram
class Subject {
<<interface>>
+request()
}
class RealSubject {
+request()
}
class Proxy {
-realSubject : RealSubject
+request()
}
Subject <|.. RealSubject
Subject <|.. Proxy
Proxy --> RealSubject : delegates
5.工厂方法模式
工厂方法模式(Factory Method Pattern) → 创建型设计模式
**工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。**通过让子类决定实例化哪个产品,将对象创建延迟到子类,从而符合开闭原则。这样,客户端调用工厂接口即可获得对象,而无需知道具体类的实现。
| 项目 | 内容 |
|---|---|
| 解决问题 | 当系统需要灵活地创建产品对象,避免简单工厂模式中工厂类集中逻辑过于臃肿,同时遵循开闭原则 |
| 核心结构 | 1. 抽象工厂(Creator):声明创建产品的抽象方法 2. 具体工厂(ConcreteCreator):实现创建具体产品的方法 3. 抽象产品(Product):定义产品接口 4. 具体产品(ConcreteProduct):实现产品接口 5. 客户端(Client):通过抽象工厂获取产品对象 |
| 应用场景 | 1. 系统有多个产品等级结构,需要独立扩展 2. 避免简单工厂集中管理对象创建导致违反开闭原则 3. 系统不关心具体产品类,只依赖抽象产品接口 |
| 优点 | - 遵循开闭原则,增加新产品无需修改已有工厂 - 客户端与具体产品解耦- 产品族扩展灵活 |
| 缺点 | - 每增加一种产品,需要增加对应工厂类,类数量增加 - 增加系统复杂度 |
public interface Product {
void use();
}
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}
public abstract class Creator {
// 工厂方法
public abstract Product createProduct();
// 模板方法(可选)
public void someOperation() {
Product product = createProduct();
product.use();
}
}
public class ConcreteCreatorA extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
public class Client(){
public static void main(String args[]){
Creator creator = new ConcreteCreatorA();
creator.someOperation();
}
}
UML类图
classDiagram
class Product {
<<interface>>
+use()
}
class ConcreteProductA {
+use()
}
class ConcreteProductB {
+use()
}
class Creator {
<<abstract>>
+createProduct() Product
+someOperation()
}
class ConcreteCreatorA {
+createProduct() Product
}
class ConcreteCreatorB {
+createProduct() Product
}
Product <|.. ConcreteProductA
Product <|.. ConcreteProductB
Creator <|-- ConcreteCreatorA
Creator <|-- ConcreteCreatorB
Creator --> Product : creates
6.原型模式
原型模式(Prototype Pattern) → 创建型设计模式
原型模式通过复制现有对象来创建新对象,而不是通过 new 关键字实例化。
这样可以在运行时动态地生成对象,并且可以保留对象的状态。
Java中Cloneable接口用来标记,防止在调用父类Object的clone方法时抛出异常(java设计原因),拥有引用类型的类中需要重写clone方法来实现深克隆
// Object.clone() 会检查,是否实现 Cloneable 是一个“权限开关” 伪代码
if (!(this instanceof Cloneable)) {
throw new CloneNotSupportedException();
}
| 项目 | 内容 |
|---|---|
| 解决问题 | 用已有对象实例创建新对象,避免重复初始化开销,解决对象创建成本高或复杂的情况 |
| 核心结构 | 1. 抽象原型(Prototype):声明克隆方法 clone()2. 具体原型(ConcretePrototype):实现克隆方法 3. 客户端(Client):通过克隆方法获取新对象,而不是直接使用 new |
| 应用场景 | 1. 对象创建成本较高(如数据库加载或复杂计算) 2. 系统中需要大量相同或相似对象 3. 想通过拷贝现有对象来避免依赖构造函数 4. 想动态增加对象类型,不依赖具体类 |
| 优点 | - 创建对象开销小 - 可动态扩展对象类型,无需修改已有类 - 避免重复初始化,提高性能 |
| 缺点 | - 克隆复杂对象时需要处理深拷贝问题 - 需要为每个类实现 clone 方法- 克隆过程可能违反封装(直接访问对象内部状态) |
public abstract class Prototype implements Cloneable {
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
class Address implements Cloneable {
String city;
public Address(String city) {
this.city = city;
}
@Override
protected Address clone() throws CloneNotSupportedException {
return (Address) super.clone();
}
}
public class ConcretePrototype implements Cloneable {
private String name;
private Address address;
public ConcretePrototype(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public ConcretePrototype clone() {
try {
ConcretePrototype copy = (ConcretePrototype) super.clone();
copy.address = address.clone(); // 关键:深拷贝
return copy;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
public class Client {
public static void main(String[] args) {
ConcretePrototype p1 = new ConcretePrototype("张三", new Address("北京"));
ConcretePrototype p2 = p1.clone();
System.out.println(p1 == p2); // false
System.out.println(p1.address == p2.address); // false(深拷贝)
}
}
UML类图
classDiagram
%% Cloneable 接口
class Cloneable {
<<interface>>
}
%% 抽象原型类
class Prototype {
<<abstract>>
+clone() Prototype
}
%% 地址类
class Address {
-String city
+Address(String city)
#clone() Address
}
%% 具体原型类
class ConcretePrototype {
-String name
-Address address
+ConcretePrototype(String name, Address address)
+clone() ConcretePrototype
}
%% 实现关系
Cloneable <|.. Prototype : implements
Cloneable <|.. Address : implements
Cloneable <|.. ConcretePrototype : implements
ConcretePrototype --> Address : has
7.模版方法模式
模板方法模式(Template Method Pattern) → 行为型设计模式
模板方法模式在一个抽象类中定义一个算法的骨架,而将某些步骤的实现延迟到子类中。 子类可以重写这些步骤,但整体算法结构不变。
| 项目 | 内容 |
|---|---|
| 解决问题 | 通过定义算法骨架,将不变部分封装在父类中,将可变部分延迟到子类实现,实现代码复用和算法复用 |
| 核心结构 | 1. 抽象类(AbstractClass):定义模板方法,包含算法骨架,并声明可变步骤的抽象方法 2. 具体子类(ConcreteClass):实现抽象方法,完成可变步骤 3. 客户端(Client):调用模板方法执行算法 |
| 应用场景 | 1. 多个子类有相似算法,只有部分步骤不同 2. 希望控制算法执行顺序,封装固定流程 3. 提高代码复用,避免重复实现 |
| 优点 | - 封装不变部分,复用算法结构 - 子类只需实现可变部分,提高扩展性 - 遵循开闭原则,算法骨架不变可扩展 |
| 缺点 | - 父类增加新的抽象步骤会影响所有子类 - 子类对模板方法的依赖强,灵活性较低 |
public abstract class AbstractClass {
// 模板方法:定义算法流程(通常 final)
public final void templateMethod() {
step1();
step2();
hook(); // 可选钩子
step3();
}
// 基本方法:公共实现
protected void step1() {
System.out.println("公共步骤1");
}
// 抽象方法:子类必须实现
protected abstract void step2();
// 钩子方法:子类可选择性覆盖
protected void hook() {
// 默认什么都不做
}
// 基本方法:公共实现
protected void step3() {
System.out.println("公共步骤3");
}
}
public class ConcreteClassA extends AbstractClass {
@Override
protected void step2() {
System.out.println("子类A实现步骤2");
}
@Override
protected void hook() {
System.out.println("子类A的钩子逻辑");
}
}
public class ConcreteClassB extends AbstractClass {
@Override
protected void step2() {
System.out.println("子类B实现步骤2");
}
}
public class Client {
public static void main(String[] args) {
AbstractClass a = new ConcreteClassA();
a.templateMethod();
AbstractClass b = new ConcreteClassB();
b.templateMethod();
}
}
UML类图
classDiagram
direction TB
class AbstractClass {
<<abstract>>
+templateMethod()
#step1()
#step2()
#hook()
#step3()
}
class ConcreteClassA {
#step2()
#hook()
}
class ConcreteClassB {
#step2()
}
%% 继承关系
AbstractClass <|-- ConcreteClassA
AbstractClass <|-- ConcreteClassB
8.外观模式
外观模式(Facade Pattern) → 结构型设计模式
外观模式为子系统提供一个统一接口,让子系统更易使用,屏蔽复杂性。 客户端通过外观接口访问子系统,而无需了解子系统的复杂内部结构。
| 项目 | 内容 |
|---|---|
| 解决问题 | 为复杂子系统提供统一接口,简化客户端调用,降低系统耦合度 |
| 核心结构 | 1. 外观类(Facade):提供统一接口,封装子系统调用 2. 子系统类(Subsystem):实现具体功能,客户端可直接调用但通常通过外观 3. 客户端(Client):通过外观调用子系统功能 |
| 应用场景 | 1. 系统复杂,包含多个子系统,需要简化调用 2. 客户端与子系统耦合度高,希望提供统一入口 3. 系统分层,希望在高层提供简洁接口 |
| 优点 | - 简化客户端使用,降低耦合 - 提高子系统独立性 - 可以逐步构建复杂系统,便于维护 |
| 缺点 | - 外观类增加新的方法时可能需要修改子系统 - 不能完全隐藏子系统的复杂性,客户端仍可直接访问 |
public class SubSystemA {
public void operationA() {
System.out.println("子系统A的操作");
}
}
public class SubSystemB {
public void operationB() {
System.out.println("子系统B的操作");
}
}
public class Facade {
private SubSystemA subsystemA;
private SubSystemB subsystemB;
public Facade() {
subsystemA = new SubSystemA();
subsystemB = new SubSystemB();
}
public void doOperation() {
System.out.println("外观统一操作开始");
subsystemA.operationA();
subsystemB.operationB();
System.out.println("外观统一操作结束");
}
}
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.doOperation(); // 一行调用,内部调用子系统
}
}
UML类图
classDiagram
direction TB
class SubSystemA {
+operationA()
}
class SubSystemB {
+operationB()
}
class Facade {
-subsystemA : SubSystemA
-subsystemB : SubSystemB
+doOperation()
}
%% 组合关系
Facade --> SubSystemA : has-a
Facade --> SubSystemB : has-a
9.建造者模式
建造者模式(Builder Pattern) → 创建型设计模式
建造者模式将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。 通过逐步构建部件,最终得到一个完整的对象。
| 项目 | 内容 |
|---|---|
| 解决问题 | 将一个复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示,解决对象创建复杂、参数多的问题 |
| 核心结构 | 1. 抽象建造者(Builder):声明构建步骤接口 2. 具体建造者(ConcreteBuilder):实现构建步骤,返回最终产品 3. 产品(Product):表示被构建的复杂对象 4. 指挥者(Director):控制构建顺序和过程 5. 客户端(Client):通过指挥者获取产品 |
| 应用场景 | 1. 对象由多个部分组成且创建复杂 2. 希望隔离复杂对象的构建和表示 3. 同样的构建过程可创建不同表示 4. 对象构建过程稳定,但内部组成可能变化 |
| 优点 | - 将复杂对象构建与表示分离 - 易于控制对象构建过程 - 可以创建不同产品,扩展性好 |
| 缺点 | - 增加类和代码复杂度 - 指挥者和建造者耦合,需要设计合理 |
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) { this.partA = partA; }
public void setPartB(String partB) { this.partB = partB; }
public void setPartC(String partC) { this.partC = partC; }
public void show() {
System.out.println("Product: " + partA + ", " + partB + ", " + partC);
}
}
public abstract class Builder {
protected Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public Product getProduct() {
return product;
}
}
public class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
product.setPartA("部件A");
}
@Override
public void buildPartB() {
product.setPartB("部件B");
}
@Override
public void buildPartC() {
product.setPartC("部件C");
}
}
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getProduct();
}
}
public class Client {
public static void main(String[] args) {
Director director = new Director(new ConcreteBuilder());
Product product = director.construct();
product.show();
}
}
UML类图
classDiagram
direction TB
class Product {
-partA : String
-partB : String
-partC : String
+setPartA(partA : String)
+setPartB(partB : String)
+setPartC(partC : String)
+show()
}
class Builder {
<<abstract>>
#product : Product
+buildPartA()
+buildPartB()
+buildPartC()
+getProduct() : Product
}
class ConcreteBuilder {
+buildPartA()
+buildPartB()
+buildPartC()
+getProduct() : Product
}
class Director {
-builder : Builder
+construct() : Product
}
%% 继承关系
Builder <|-- ConcreteBuilder
%% 组合关系
ConcreteBuilder --> Product : builds
Director --> Builder : uses
10.观察者模式
观察者模式(Observer Pattern) → 行为型设计模式
观察者模式定义对象间的一种一对多依赖关系,当一个对象(被观察者)状态发生改变时,它的所有依赖者(观察者)都会自动收到通知并更新。也叫做发布---订阅模式(Publish/Subscribe)
| 项目 | 内容 |
|---|---|
| 解决问题 | 建立对象间一对多依赖关系,当一个对象状态变化时,所有依赖者自动收到通知并更新,实现解耦 |
| 核心结构 | 1. 抽象主题(Subject):维护观察者列表,提供注册、移除、通知方法 2. 具体主题(ConcreteSubject):实现主题状态变化逻辑,并通知观察者 3. 抽象观察者(Observer):定义更新接口 4. 具体观察者(ConcreteObserver):实现更新接口,响应主题变化 5. 客户端(Client):注册观察者,触发主题变化 |
| 应用场景 | 1. 一个对象的变化需要同时更新其他对象 2. 对象间存在动态依赖关系 3. 事件驱动系统,如 GUI 事件、消息订阅 |
| 优点 | - 主题和观察者解耦,符合开闭原则 - 支持广播通信,一个主题可有多个观察者 |
| 缺点 | - 观察者过多,通知开销大 - 可能引起循环依赖或更新延迟 - 观察者顺序不易控制 |
public interface Observer {
void update(String message);
}
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void setState(String state) {
this.state = state;
notifyObservers();
}
public String getState() {
return state;
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到通知:" + message);
}
}
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer o1 = new ConcreteObserver("观察者A");
Observer o2 = new ConcreteObserver("观察者B");
subject.attach(o1);
subject.attach(o2);
subject.setState("状态发生变化");
}
}
UML类图
classDiagram
%% Observer 接口
class Observer {
<<interface>>
+update(message: String)
}
%% Subject 接口
class Subject {
<<interface>>
+attach(observer: Observer)
+detach(observer: Observer)
+notifyObservers()
}
%% 具体被观察者
class ConcreteSubject {
-observers: List<Observer>
-state: String
+setState(state: String)
+getState(): String
+attach(observer: Observer)
+detach(observer: Observer)
+notifyObservers()
}
%% 具体观察者
class ConcreteObserver {
-name: String
+ConcreteObserver(name: String)
+update(message: String)
}
%% 关系
ConcreteSubject ..|> Subject : implements
ConcreteObserver ..|> Observer : implements
ConcreteSubject "1" o-- "*" Observer : maintains
11.抽象工厂模式
抽象工厂模式(Abstract Factory Pattern) → 创建型设计模式
抽象工厂模式提供一个接口,用于创建一系列相关或依赖的对象,而无需指定它们的具体类。 它通过工厂的工厂(Factory of Factories)封装了对象族的创建,使得客户端只依赖抽象接口。
| 项目 | 内容 |
|---|---|
| 解决问题 | 提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类,解决产品族扩展和客户端解耦问题 |
| 核心结构 | 1. 抽象工厂(AbstractFactory):声明创建一系列产品的接口 2. 具体工厂(ConcreteFactory):实现抽象工厂接口,创建具体产品 3. 抽象产品(AbstractProduct):定义产品接口 4. 具体产品(ConcreteProduct):实现产品接口 5. 客户端(Client):使用抽象工厂创建产品,依赖抽象接口 |
| 应用场景 | 1. 系统有多个产品族,而客户端只使用某一族产品 2. 希望确保同一产品族的对象一起使用 3. 需要解耦具体类的创建,便于产品族扩展 |
| 优点 | - 提供产品族一致性 - 客户端无需依赖具体类,实现解耦 - 遵循开闭原则,便于扩展产品族 |
| 缺点 | - 增加系统类和接口数量 - 扩展产品等级结构(增加新产品)需要修改抽象工厂接口,影响开闭性 |
public interface UserRepository {
void saveUser();
}
public interface OrderRepository {
void saveOrder();
}
// MySQL 产品族
public class MySQLUserRepository implements UserRepository {
@Override
public void saveUser() {
System.out.println("MySQL 保存用户");
}
}
public class MySQLOrderRepository implements OrderRepository {
@Override
public void saveOrder() {
System.out.println("MySQL 保存订单");
}
}
// MongoDB 产品族
public class MongoUserRepository implements UserRepository {
@Override
public void saveUser() {
System.out.println("MongoDB 保存用户");
}
}
public class MongoOrderRepository implements OrderRepository {
@Override
public void saveOrder() {
System.out.println("MongoDB 保存订单");
}
}
// 接口工厂
public interface RepositoryFactory {
UserRepository createUserRepository();
OrderRepository createOrderRepository();
}
public class MySQLRepositoryFactory implements RepositoryFactory {
@Override
public UserRepository createUserRepository() {
return new MySQLUserRepository();
}
@Override
public OrderRepository createOrderRepository() {
return new MySQLOrderRepository();
}
}
public class MongoRepositoryFactory implements RepositoryFactory {
@Override
public UserRepository createUserRepository() {
return new MongoUserRepository();
}
@Override
public OrderRepository createOrderRepository() {
return new MongoOrderRepository();
}
}
public class Client {
public static void main(String[] args) {
RepositoryFactory repositoryFactory = new MongoRepositoryFactory();
UserRepository userRepository = rf.createUserRepository();
OrderRepository orderRepository = rf.createOrderRepository();
userRepository.saveUser();
orderRepository.saveOrder();
}
}
UML类图
classDiagram
class UserRepository {
<<interface>>
+saveUser()
}
class OrderRepository {
<<interface>>
+saveOrder()
}
class MySQLUserRepository {
+saveUser()
}
class MySQLOrderRepository {
+saveOrder()
}
class MongoUserRepository {
+saveUser()
}
class MongoOrderRepository {
+saveOrder()
}
class RepositoryFactory {
<<interface>>
+createUserRepository()
+createOrderRepository()
}
class MySQLRepositoryFactory {
+createUserRepository()
+createOrderRepository()
}
class MongoRepositoryFactory {
+createUserRepository()
+createOrderRepository()
}
%% 继承 / 实现关系
UserRepository <|.. MySQLUserRepository
UserRepository <|.. MongoUserRepository
OrderRepository <|.. MySQLOrderRepository
OrderRepository <|.. MongoOrderRepository
RepositoryFactory <|.. MySQLRepositoryFactory
RepositoryFactory <|.. MongoRepositoryFactory
%% 工厂依赖 / 聚合产品
MySQLRepositoryFactory ..> UserRepository : create
MySQLRepositoryFactory ..> OrderRepository : create
MongoRepositoryFactory ..> UserRepository : create
MongoRepositoryFactory ..> OrderRepository : create
12.状态模式
状态模式(State Pattern) → 行为型设计模式
状态模式允许对象在内部状态改变时改变其行为,看起来像改变了对象的类。 它将每种状态封装成独立类,使对象在不同状态下表现出不同的行为,同时状态转换由状态对象自己控制。
| 项目 | 内容 |
|---|---|
| 解决问题 | 允许对象在内部状态改变时改变行为,将状态相关逻辑从对象中抽离,避免大量条件判断(if-else 或 switch) |
| 核心结构 | 1. 抽象状态(State):定义状态接口,声明对应行为 2. 具体状态(ConcreteState):实现不同状态的行为 3. 环境类(Context):持有当前状态对象,状态变化时委托行为给当前状态 4. 客户端(Client):与环境类交互,触发状态变化 |
| 应用场景 | 1. 对象的行为依赖其状态,并且状态会频繁变化 2. 行为随状态变化而变化,避免条件语句过多 3. 想将状态行为封装在独立类中,增强可维护性 |
| 优点 | - 将状态和行为封装在独立类中,提高可维护性 - 避免大量条件判断- 状态扩展方便,符合开闭原则 |
| 缺点 | - 增加系统类和对象数量 - 状态之间切换逻辑复杂时,需要谨慎设计 |
public interface State {
void handle(Context context);
}
public class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("当前是状态 A,执行 A 的行为");
// 状态切换
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("当前是状态 B,执行 B 的行为");
// 状态切换
context.setState(new ConcreteStateA());
}
}
public class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.request(); // A → B
context.request(); // B → A
}
}
UML类图
classDiagram
class State {
<<interface>>
+handle(context: Context)
}
class Context {
-state: State
+Context(state: State)
+setState(state: State)
+request()
}
class ConcreteStateA {
+handle(context: Context)
}
class ConcreteStateB {
+handle(context: Context)
}
State <|.. ConcreteStateA
State <|.. ConcreteStateB
Context --> State
13.适配器模式
适配器模式(Adapter Pattern) → 结构型设计模式
适配器模式将一个类的接口转换成客户端期望的另一个接口,使原本由于接口不兼容而无法一起工作的类可以协同工作。
| 项目 | 内容 |
|---|---|
| 解决问题 | 将一个类的接口转换为客户端期望的接口,使原本由于接口不兼容而无法一起工作的类可以协同工作 |
| 核心结构 | 1. 目标接口(Target):定义客户端期望的接口 2. 适配者类(Adaptee):已有接口,需要适配 3. 适配器(Adapter):实现目标接口,并在内部调用适配者方法 4. 客户端(Client):通过目标接口调用功能 |
| 应用场景 | 1. 系统需要使用现有类,但接口不匹配 2. 希望通过适配器复用已有类 3. 系统需要统一接口,屏蔽接口差异 |
| 优点 | - 提高类的复用性- 解耦客户端和具体类 - 可以使用现有类而不修改其源代码 |
| 缺点 | - 增加系统类和对象数量- 适配器层次过多时,增加复杂度 - 对系统理解和调试可能造成一定困难 |
public interface Target {
void request();
}
// 被适配者
public class Adaptee {
public void specificRequest() {
System.out.println("执行原有方法 specificRequest");
}
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 委托给 Adaptee,同时做必要转换
adaptee.specificRequest();
}
}
public class Client {
public static void main(String[] args) {
Target target = new Adapter(new Adaptee());
target.request();
}
}
UML类图
classDiagram
class Target {
<<interface>>
+request()
}
class Adapter {
-adaptee: Adaptee
+Adapter(adaptee: Adaptee)
+request()
}
class Adaptee {
+specificRequest()
}
Target <|.. Adapter
Adapter --> Adaptee : uses
14.备忘录模式
备忘录模式(Memento Pattern) → 行为型设计模式
备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在需要时恢复该状态。 它将状态存储与操作分离,允许恢复到某一历史状态。
| 项目 | 内容 |
|---|---|
| 解决问题 | 在不破坏封装性的前提下,保存对象的内部状态,以便在以后恢复,常用于撤销操作或状态回滚 |
| 核心结构 | 1. 备忘录(Memento):存储对象状态,不暴露内部细节 2. 发起人(Originator):创建备忘录并可根据备忘录恢复状态 3. 管理者(Caretaker):保存备忘录,不能修改内容,只负责传递和管理 4. 客户端(Client):通过发起人创建和恢复备忘录 |
| 应用场景 | 1. 需要保存和恢复对象状态的场景,如撤销、历史记录 2. 希望保持封装性,不暴露对象内部实现 3. 对象状态变化复杂,直接保存快照更方便 |
| 优点 | - 保存和恢复对象状态,便于撤销操作 - 保持封装性,不暴露内部细节- 易于实现历史记录和状态管理 |
| 缺点 | - 可能占用大量内存(保存多个备份) - 增加系统复杂度- 需要合理管理备忘录生命周期 |
public class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("当前状态: " + state);
}
public String getState() {
return state;
}
// 创建备忘录
public Memento saveStateToMemento() {
return new Memento(state);
}
// 从备忘录恢复
public void getStateFromMemento(Memento memento) {
state = memento.getState();
System.out.println("恢复状态: " + state);
}
}
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
public class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("状态 #1");
originator.setState("状态 #2");
caretaker.add(originator.saveStateToMemento()); // 保存状态 #2
originator.setState("状态 #3");
caretaker.add(originator.saveStateToMemento()); // 保存状态 #3
originator.setState("状态 #4");
// 恢复状态
originator.getStateFromMemento(caretaker.get(0)); // 恢复到状态 #2
originator.getStateFromMemento(caretaker.get(1)); // 恢复到状态 #3
}
}
UML类图
classDiagram
class Originator {
-state: String
+setState(state: String)
+getState(): String
+saveStateToMemento(): Memento
+getStateFromMemento(m: Memento)
}
class Memento {
-state: String
+Memento(state: String)
+getState(): String
}
class Caretaker {
-mementoList: List~Memento~
+add(m: Memento)
+get(index: int): Memento
}
Originator --> Memento : creates
Caretaker --> Memento : manages
15.组合模式
组合模式(Composite Pattern) → 结构型设计模式
组合模式将对象组合成树形结构以表示“部分-整体”的层次结构,使客户端可以统一对待单个对象和组合对象。“统一对单个对象和组合对象的操作”
| 项目 | 内容 |
|---|---|
| 解决问题 | 将对象组合成树形结构以表示“整体-部分”关系,使客户端可以统一处理单个对象和组合对象,简化树形结构操作 |
| 核心结构 | 1. 组件(Component):定义统一接口,包括叶子和组合对象的公共操作 2. 叶子(Leaf):表示树的叶节点,实现组件接口 3. 组合对象(Composite):包含子组件,实现统一接口,管理子节点 4. 客户端(Client):通过组件接口操作叶子和组合对象 |
| 应用场景 | 1. 系统中对象具有树形结构,如文件目录、组织结构 2. 希望客户端忽略单个对象与组合对象的差异,统一操作 3. 对象层次结构经常发生变化,需要动态组合 |
| 优点 | - 客户端统一处理叶子和组合对象,简化操作 - 树形结构易于扩展和管理 - 符合开闭原则,增加新类型不影响客户端 |
| 缺点 | - 设计较复杂,类数量增加 - 叶子和组合对象接口一致,可能引入不适用的方法 - 调试树形结构时可能较困难 |
public interface Component {
void operation();
}
public class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("Leaf " + name + " 执行操作");
}
}
public class Composite implements Component {
private String name;
private List<Component> children = new ArrayList<>();
public Composite(String name) {
this.name = name;
}
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
System.out.println("Composite " + name + " 执行操作");
for (Component child : children) {
child.operation();
}
}
}
public class Client {
public static void main(String[] args) {
Leaf leaf1 = new Leaf("叶子1");
Leaf leaf2 = new Leaf("叶子2");
Composite composite = new Composite("组合1");
composite.add(leaf1);
composite.add(leaf2);
Composite root = new Composite("根组合");
root.add(composite);
root.operation();
}
}
UML类图
classDiagram
class Component {
<<interface>>
+operation()
}
class Leaf {
-name: String
+Leaf(name: String)
+operation()
}
class Composite {
-name: String
-children: List~Component~
+Composite(name: String)
+add(c: Component)
+remove(c: Component)
+operation()
}
Component <|.. Leaf
Component <|.. Composite
Composite o-- Component : contains
16.迭代器模式
迭代器模式(Iterator Pattern) → 行为型设计模式
迭代器模式提供一种方法顺序访问集合对象中的各个元素,而又不暴露该对象的内部表示。 它将遍历逻辑从集合对象中抽离出来,让客户端以统一方式访问集合元素。
| 项目 | 内容 |
|---|---|
| 解决问题 | 提供一种顺序访问集合对象元素的方法,而无需暴露集合内部表示,实现集合遍历的解耦 |
| 核心结构 | 1. 迭代器接口(Iterator):定义访问和遍历集合元素的接口(如 hasNext()、next())2. 具体迭代器(ConcreteIterator):实现迭代器接口,记录当前遍历位置 3. 聚合接口(Aggregate):提供创建迭代器的方法 4. 具体聚合(ConcreteAggregate):实现聚合接口,返回具体迭代器 5. 客户端(Client):通过迭代器访问集合元素 |
| 应用场景 | 1. 需要遍历集合对象,而不暴露内部结构 2. 系统支持多种遍历方式(正序、逆序等) 3. 希望统一访问接口,支持不同类型集合 |
| 优点 | - 遍历集合和集合本身解耦 - 可以为不同集合提供一致遍历接口 - 支持多种遍历方式,灵活性高 |
| 缺点 | - 增加额外类和接口 - 对小型集合可能略显冗余 - 复杂遍历逻辑需要在迭代器中实现,增加系统复杂度 |
// 迭代器接口
public interface Iterator<T> {
boolean hasNext();
T next();
}
// 具体迭代器
public class ConcreteIterator<T> implements Iterator<T> {
private T[] items;
private int position = 0;
public ConcreteIterator(T[] items) {
this.items = items;
}
@Override
public boolean hasNext() {
return position < items.length;
}
@Override
public T next() {
return items[position++];
}
}
// 聚合接口
public interface Aggregate<T> {
Iterator<T> createIterator();
}
// 具体聚合
public class ConcreteAggregate<T> implements Aggregate<T> {
private T[] items;
public ConcreteAggregate(T[] items) {
this.items = items;
}
@Override
public Iterator<T> createIterator() {
return new ConcreteIterator<>(items);
}
}
public class Client {
public static void main(String[] args) {
String[] names = {"Alice", "Bob", "Charlie"};
Aggregate<String> aggregate = new ConcreteAggregate<>(names);
Iterator<String> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
UML类图
classDiagram
class Iterator {
<<interface>>
+hasNext() : boolean
+next() : T
}
class ConcreteIterator {
-items : T[]
-position : int
+hasNext() : boolean
+next() : T
}
class Aggregate {
<<interface>>
+createIterator() : Iterator
}
class ConcreteAggregate {
-items : T[]
+createIterator() : Iterator
}
ConcreteIterator ..> Iterator : implements
ConcreteAggregate ..> Aggregate : implements
17.单例模式
单例模式(Singleton Pattern) → 创建型设计模式
单例模式确保一个类只有一个实例,并提供一个全局访问点。 它控制实例化过程,保证系统中共享对象唯一性。
| 项目 | 内容 |
|---|---|
| 解决问题 | 确保一个类只有一个实例,并提供全局访问点,避免重复创建对象造成资源浪费或状态不一致 |
| 核心结构 | 1. 单例类(Singleton):私有构造函数,静态方法返回唯一实例 2. 客户端(Client):通过单例类提供的访问方法获取唯一实例 |
| 应用场景 | 1. 系统需要唯一实例,如配置管理、日志管理、线程池 2. 控制资源共享或全局访问 3. 避免频繁创建销毁对象带来的开销 |
| 优点 | - 保证实例唯一性 - 提供全局访问点 - 延迟实例化(可选,节约资源) |
| 缺点 | - 扩展困难(继承单例类不易) - 多线程环境需考虑同步,增加复杂度 - 可能引入全局状态,降低模块化和可测试性 |
如果 instance 不是 volatile,可能出现:
- 线程 A 开始创建对象,但构造还没执行完
- 线程 B 看到
instance != null,直接返回 → 使用了未初始化的对象
加上 volatile:
- 禁止重排序,确保 对象完全初始化后才被引用
- 保证多线程下安全
volatile 修饰变量有两个主要作用:
-
可见性(Visibility)
- 当一个线程修改了
volatile变量的值,其他线程可以立即看到这个修改。 - 在单例模式中,保证线程看到的
instance是最新创建的对象。
- 当一个线程修改了
-
禁止指令重排序(Atomicity / Ordering)
-
JVM 在优化代码时可能对指令进行重排序
-
对象创建实际上分三步:
-
分配内存空间
-
调用构造函数初始化对象
-
把 instance 指向分配的内存地址
-
如果没有
volatile,可能发生 重排序,导致步骤 3 提前执行:-
重排序是 JVM 或 CPU 为了优化性能,在保证单线程语义下改变指令执行顺序的一种行为
-
重排序可能发生的情况
JVM 为了优化,可能把 步骤 3 提前到步骤 2 前,顺序变成:
- 分配内存
- 引用赋值 →
instance指向未初始化对象 - 初始化对象
-
-
其他线程看到
instance != null时,实际对象还没初始化完 → 访问未初始化对象 → 出错
-
-
-
-
// 饿汉式单例模式
public class Singleton{
private static Singleton instance = new Singleton();
private Signleton() {}
public static Singleton getInstance(){
return instance;
}
}
// 懒汉式单例模式
public class Singleton {
// volatile 保证多线程下可见性
private static volatile Singleton instance;
// 私有构造函数
private Singleton() {}
// 获取唯一实例,懒加载,线程安全
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) { // 双重检查锁
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
public void doSomething() {
System.out.println("执行单例方法");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); // true
s1.doSomething();
}
}
UML类图
classDiagram
class Singleton {
-instance : Singleton
-Singleton()
+getInstance() : Singleton
+doSomething()
}
18.桥接模式
桥接模式(Bridge Pattern) → 结构型设计模式
桥接模式将抽象部分与实现部分分离,使它们可以独立变化。 通过组合关系,将抽象接口和具体实现解耦,从而提高系统的灵活性和可扩展性。 实现系统可能有多个角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们单独变化,减少它们之间的耦合。
| 项目 | 内容 |
|---|---|
| 解决问题 | 将抽象与实现分离,使它们可以独立变化,避免类爆炸和实现耦合过紧 |
| 核心结构 | 1. 抽象类(Abstraction):定义抽象接口,持有实现类引用 2. 修正抽象类(RefinedAbstraction):扩展抽象接口 3. 实现接口(Implementor):定义实现类接口 4. 具体实现类(ConcreteImplementor):实现实现接口 5. 客户端(Client):通过抽象类调用接口功能 |
| 应用场景 | 1. 抽象和实现可能独立扩展 2. 避免继承导致的类爆炸 3. 系统需要在多个维度上扩展,如操作系统和设备类型 4. 想把抽象部分与实现部分解耦,提高灵活性 |
| 优点 | - 抽象与实现分离,独立扩展 - 避免类爆炸 - 提高系统灵活性和可维护性 |
| 缺点 | - 增加系统复杂度,类和对象增多 - 设计需要明确抽象和实现的边界,否则会混乱 |
// 实现类接口
public interface Implementor {
void operationImpl();
}
// 具体实现类A
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorA 实现具体操作");
}
}
// 具体实现类B
public class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
System.out.println("ConcreteImplementorB 实现具体操作");
}
}
// 抽象类
public abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
public abstract void operation();
}
// 扩展抽象
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
System.out.println("RefinedAbstraction 执行操作...");
implementor.operationImpl();
}
}
public class Client {
public static void main(String[] args) {
Implementor implA = new ConcreteImplementorA();
Abstraction abs1 = new RefinedAbstraction(implA);
abs1.operation();
Implementor implB = new ConcreteImplementorB();
Abstraction abs2 = new RefinedAbstraction(implB);
abs2.operation();
}
}
UML类图
classDiagram
class Implementor {
<<interface>>
+operationImpl()
}
class ConcreteImplementorA {
+operationImpl()
}
class ConcreteImplementorB {
+operationImpl()
}
class Abstraction {
-implementor : Implementor
+operation()
}
class RefinedAbstraction {
+operation()
}
ConcreteImplementorA ..> Implementor : implements
ConcreteImplementorB ..> Implementor : implements
RefinedAbstraction --|> Abstraction : extends
Abstraction --> Implementor : "has-a"
19.命令模式
命令模式(Command Pattern) → 行为型设计模式
命令模式将一个请求封装为一个对象,从而使你可以用不同的请求、队列或者日志来参数化对象,并支持可撤销操作。 它将请求的发送者与执行者解耦。
| 项目 | 内容 |
|---|---|
| 解决问题 | 将请求封装为对象,从而实现请求的参数化、队列化、撤销/重做等操作,解耦请求发送者和接收者 |
| 核心结构 | 1. 命令接口(Command):声明执行操作的接口 2. 具体命令(ConcreteCommand):实现命令接口,绑定接收者并调用其操作 3. 接收者(Receiver):知道如何执行请求相关操作 4. 调用者(Invoker):持有命令对象,调用命令执行请求 5. 客户端(Client):创建具体命令并设置接收者、调用者 |
| 应用场景 | 1. 需要将请求调用者与执行者解耦 2. 需要支持撤销/重做功能 3. 需要将请求记录、排队、日志化 4. 支持宏命令,将多个命令组合成一个操作 |
| 优点 | - 请求发送者与接收者解耦 - 支持撤销/重做和宏命令 - 易于扩展新的命令 |
| 缺点 | - 系统会增加许多命令类,增加复杂度 - 设计稍显冗长,简单场景可能过度设计 |
// Command
public interface Command {
void execute();
}
// Receiver
public class Light {
public void turnOn() {
System.out.println("灯打开");
}
public void turnOff() {
System.out.println("灯关闭");
}
}
// ConcreteCommand 开灯
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
// 关灯
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
// Invoker
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// Client
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command onCommand = new LightOnCommand(light);
Command offCommand = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(onCommand);
remote.pressButton();
remote.setCommand(offCommand);
remote.pressButton();
}
}
UML类图
classDiagram
class Command {
<<interface>>
+execute()
}
class Light {
+turnOn()
+turnOff()
}
class LightOnCommand {
-light : Light
+execute()
}
class LightOffCommand {
-light : Light
+execute()
}
class RemoteControl {
-command : Command
+setCommand(Command)
+pressButton()
}
LightOnCommand ..> Command : implements
LightOffCommand ..> Command : implements
LightOnCommand --> Light : depends
LightOffCommand --> Light : depends
RemoteControl --> Command : uses
20.职责链模式
职责链模式(Chain of Responsibility Pattern) → 行为型设计模式
职责链模式为请求创建一条链,并沿着链传递请求,直到某个处理对象处理它。 它将请求的发送者和处理者解耦,让多个对象有机会处理请求。
| 项目 | 内容 |
|---|---|
| 解决问题 | 将请求的发送者和接收者解耦,使多个对象都有机会处理请求,避免请求处理的硬编码条件判断 |
| 核心结构 | 1. 抽象处理者(Handler):定义处理请求接口及后继链引用 2. 具体处理者(ConcreteHandler):实现处理请求逻辑,可选择处理或传递给下一个处理者 3. 客户端(Client):构建链条并提交请求 |
| 应用场景 | 1. 系统中有多个对象可处理同一请求,但具体处理者不固定 2. 需要动态指定处理顺序 3. 希望降低发送者与接收者耦合度 |
| 优点 | - 请求发送者与接收者解耦 - 增加或修改处理环节方便 - 支持动态调整责任链 |
| 缺点 | - 链过长可能影响性能 - 调试困难,容易出现请求无人处理 - 不易控制处理顺序,链条复杂时可能引发逻辑错误 |
// 抽象处理者
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(int request);
}
// 具体处理者A
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int request) {
if (request <= 10) {
System.out.println("HandlerA 处理请求:" + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 具体处理者B
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int request) {
if (request <= 20) {
System.out.println("HandlerB 处理请求:" + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 具体处理者C
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(int request) {
if (request <= 30) {
System.out.println("HandlerC 处理请求:" + request);
} else {
System.out.println("请求无法处理:" + request);
}
}
}
public class Client {
public static void main(String[] args) {
Handler h1 = new ConcreteHandlerA();
Handler h2 = new ConcreteHandlerB();
Handler h3 = new ConcreteHandlerC();
h1.setNext(h2);
h2.setNext(h3);
h1.handleRequest(5); //A处理
h1.handleRequest(15); //B处理
h1.handleRequest(25); //c处理
h1.handleRequest(35); //无法处理
}
}
UML类图
classDiagram
class Handler {
<<abstract>>
-next : Handler
+setNext(Handler)
+handleRequest(int)
}
class ConcreteHandlerA {
+handleRequest(int)
}
class ConcreteHandlerB {
+handleRequest(int)
}
class ConcreteHandlerC {
+handleRequest(int)
}
ConcreteHandlerA --|> Handler : extends
ConcreteHandlerB --|> Handler : extends
ConcreteHandlerC --|> Handler : extends
Handler --> Handler : next
21.中介模式
中介者模式(Mediator Pattern) → 行为型设计模式
中介者模式通过一个中介对象封装一系列对象之间的交互,使各对象不直接引用对方,从而降低耦合。 所有对象通过中介者通信,改变彼此的依赖关系。
| 项目 | 内容 |
|---|---|
| 解决问题 | 用一个中介对象封装对象之间的交互,使对象不需要显式引用彼此,降低对象间耦合度 |
| 核心结构 | 1. 抽象中介者(Mediator):定义同事对象通信接口 2. 具体中介者(ConcreteMediator):实现具体交互逻辑,协调各同事对象 3. 同事类(Colleague):知道中介者并通过中介者与其他同事通信 4. 客户端(Client):通过中介者间接协调同事对象 |
| 应用场景 | 1. 系统中对象之间存在复杂依赖关系 2. 希望降低对象之间耦合,提高可维护性 3. 系统中交互行为频繁变化,需要集中管理 |
| 优点 | - 降低类之间耦合- 集中控制交互逻辑,便于维护 - 可以独立改变中介逻辑而不影响同事对象 |
| 缺点 | - 中介者可能过于复杂,承担过多逻辑 - 系统规模大时,中介者设计难度增加 - 过度依赖中介者可能形成“上帝对象” |
public interface Mediator {
void send(String message, Colleague colleague);
}
public abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
public class User extends Colleague {
private String name;
public User(Mediator mediator, String name) {
super(mediator);
this.name = name;
}
public void send(String msg) {
mediator.send(msg, this);
}
public void receive(String msg) {
System.out.println(name + " 收到消息:" + msg);
}
}
public class ChatRoomMediator implements Mediator {
private List<User> users = new ArrayList<>();
public void register(User user) {
users.add(user);
}
@Override
public void send(String message, Colleague sender) {
for (User user : users) {
if (user != sender) {
user.receive(message);
}
}
}
}
public class Client {
public static void main(String[] args) {
// 1. 创建中介
ChatRoomMediator mediator = new ChatRoomMediator();
// 2. 创建同事(用户)
User u1 = new User(mediator, "Alice");
User u2 = new User(mediator, "Bob");
User u3 = new User(mediator, "Charlie");
// 3. 注册到中介
mediator.register(u1);
mediator.register(u2);
mediator.register(u3);
// 4. 发起交互
u1.send("大家好!");
u2.send("你好 Alice");
}
}
UML类图
classDiagram
direction TB
class Mediator {
<<interface>>
+send(message : String, colleague : Colleague)
}
class Colleague {
<<abstract>>
-mediator : Mediator
}
class User {
-name : String
+send(msg : String)
+receive(msg : String)
}
class ChatRoomMediator {
-users : List~User~
+register(user : User)
+send(message : String, sender : Colleague)
}
Mediator <|.. ChatRoomMediator
Colleague <|-- User
User ..> Mediator
ChatRoomMediator o-- User
22.享元模式
享元模式(Flyweight Pattern) → 结构型设计模式
享元模式通过共享对象来减少内存使用量,适用于大量相似对象的场景。 它将对象的内部状态(可共享)与外部状态(不可共享)分离,实现对象复用。
| 项目 | 内容 |
|---|---|
| 解决问题 | 通过共享对象来减少内存消耗,适用于大量相似对象场景,实现对象复用和高效管理 |
| 核心结构 | 1. 抽象享元(Flyweight):定义共享接口 2. 具体享元(ConcreteFlyweight):实现共享对象,存储内部状态 3. 非共享享元(UnsharedConcreteFlyweight,可选):存储外部状态,不被共享 4. 享元工厂(FlyweightFactory):管理共享对象池,确保对象复用 5. 客户端(Client):通过工厂获取享元对象并使用 |
| 应用场景 | 1. 系统中有大量相似对象,占用大量内存 2. 对象可分为内部状态(共享)和外部状态(外部管理) 3. 性能和内存优化需求高,如文本处理、图形渲染、棋盘游戏 |
| 优点 | - 大幅减少对象数量,节省内存 - 对象共享,提高性能 - 外部状态可灵活管理,复用性高 |
| 缺点 | - 增加系统复杂度 - 内部状态和外部状态分离设计难度较高 - 对象的共享和复用需要严格管理,否则容易出现状态错误 |
// Flyweight 抽象
public interface Flyweight {
void draw(ExternalState state);
}
// 外部状态(不共享)
public class ExternalState {
public final int x;
public final int y;
public ExternalState(int x, int y) {
this.x = x;
this.y = y;
}
}
// ConcreteFlyweight(共享)
public class CharacterFlyweight implements Flyweight {
private final char c; // 内部状态
private final String font; // 内部状态
public CharacterFlyweight(char c, String font) {
this.c = c;
this.font = font;
}
@Override
public void draw(ExternalState state) {
System.out.println(
c + " font=" + font +
" at (" + state.x + "," + state.y + ")"
);
}
}
public class CharacterFactory {
private static final Map<String, Flyweight> pool = new HashMap<>();
public static Flyweight get(char c, String font) {
String key = c + "-" + font;
//如果池里已经有这个字符的享元对象,就直接用,如果没有,就创建一个新的放进去,再返回
return pool.computeIfAbsent(
key,
k -> new CharacterFlyweight(c, font)
);
}
}
public class Client {
public static void main(String[] args){
CharacterFlyweight a1 = CharacterFactory.get('A-Arial');
a1.draw(10, 20);
CharacterFlyweight a2 = CharacterFactory.get('A-Arial');
a2.draw(30, 40);
// a1 == a2 ✅
}
}
UML类图
classDiagram
class Flyweight {
<<interface>>
+draw(state: ExternalState)
}
class ExternalState {
+x: int
+y: int
}
class CharacterFlyweight {
-c: char
-font: String
+CharacterFlyweight(c: char, font: String)
+draw(state: ExternalState)
}
class CharacterFactory {
-pool: Map<String, Flyweight>
+get(c: char, font: String) Flyweight
}
Flyweight <|.. CharacterFlyweight
CharacterFactory --> Flyweight : "creates / manages"
CharacterFlyweight ..> ExternalState : "uses (external state)"
23.解释器模式
解释器模式(Interpreter Pattern) → 行为型设计模式
解释器模式为某种语言定义语法表示,并提供一个解释器来解释语言中的句子。 它将文法规则封装成类体系,通过组合和递归实现复杂表达式的解析和执行。
| 项目 | 内容 |
|---|---|
| 解决问题 | 为特定语言或表达式设计解释器,使系统可以解释语言语法,将文法规则封装为类,便于扩展和维护 |
| 核心结构 | 1. 抽象表达式(AbstractExpression):声明解释操作接口 2. 终结符表达式(TerminalExpression):实现抽象表达式,处理基本元素 3. 非终结符表达式(NonTerminalExpression):组合其他表达式,实现复杂语法 4. 环境(Context):存储解释器需要的全局信息 5. 客户端(Client):构建表达式树,调用解释方法 |
| 应用场景 | 1. 系统需要处理自定义语言、表达式或规则 2. 文法规则稳定且易变化 3. 可以通过组合表达式类形成复杂语法结构 4. 例如:正则表达式、SQL解析、数学公式计算 |
| 优点 | - 文法易于扩展,增加新规则只需增加类 - 解释过程封装,结构清晰 - 可以使用组合模式构建复杂语法树 |
| 缺点 | - 类数量可能急剧增加,复杂度高 - 对复杂文法,效率可能较低 - 维护表达式类需要深入理解文法规则 |
| 类型 | 作用 | 举例 |
|---|---|---|
| 终结符 | 语法的原子元素,不可再分 | 数字 1, 2, 3;字符 ‘A’ |
| 非终结符 | 由子表达式组合成更复杂的语法 | 加法表达式 +、减法表达式 -、规则组合 [A-Z]+ |
// 抽象表达式
public interface Expression {
int interpret();
}
// 终结符表达式
public class NumberExpression implements Expression {
private final int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
// 非终结符表达式(加法)
public class AddExpression implements Expression {
private final Expression left;
private final Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
// 非终结符表达式(减法)
public class SubtractExpression implements Expression {
private final Expression left;
private final Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
public class Client {
public static void main(String[] args) {
Expression expr = new AddExpression(
new NumberExpression(5),
new SubtractExpression(
new NumberExpression(10),
new NumberExpression(3)
)
);
System.out.println("结果: " + expr.interpret()); // 5 + (10-3) = 12
}
}
UML类图
classDiagram
class Expression {
<<interface>>
+interpret() int
}
class NumberExpression {
-number: int
+NumberExpression(number: int)
+interpret() int
}
class AddExpression {
-left: Expression
-right: Expression
+AddExpression(left: Expression, right: Expression)
+interpret() int
}
class SubtractExpression {
-left: Expression
-right: Expression
+SubtractExpression(left: Expression, right: Expression)
+interpret() int
}
Expression <|.. NumberExpression
Expression <|.. AddExpression
Expression <|.. SubtractExpression
24.访问者模式
访问者模式(Visitor Pattern) → 行为型设计模式
访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。 它将数据结构与操作分离,将操作封装到访问者对象中。适用于数据结构相对稳定的系统
| 项目 | 内容 |
|---|---|
| 解决问题 | 在不改变元素类的前提下,为对象结构添加新的操作,解耦数据结构和操作,实现操作的灵活扩展 |
| 核心结构 | 1. 抽象访问者(Visitor):声明对每种具体元素访问的方法 2. 具体访问者(ConcreteVisitor):实现具体操作逻辑 3. 抽象元素(Element):定义 accept 方法,接受访问者4. 具体元素(ConcreteElement):实现 accept 方法,调用访问者对应方法5. 对象结构(ObjectStructure):管理元素集合,遍历元素并接收访问者 6. 客户端(Client):将访问者传入对象结构,执行操作 |
| 应用场景 | 1. 对象结构稳定,但需要不断增加新的操作 2. 不希望修改对象类来增加功能 3. 对象结构中对象类型较多,需要对不同类型做不同操作 |
| 优点 | - 增加新操作易于扩展- 将操作集中到访问者类,简化元素类 - 对象结构和操作解耦,提高可维护性 |
| 缺点 | - 增加新元素类不易,需要修改访问者接口 - 对象结构较复杂时,访问者逻辑复杂- 违背了“依赖倒置”,访问者依赖具体元素类 |
// 抽象元素
public interface Element {
void accept(Visitor visitor);
}
// 具体元素
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationA() {
System.out.println("ConcreteElementA 的操作");
}
}
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public void operationB() {
System.out.println("ConcreteElementB 的操作");
}
}
// 抽象访问者
public interface Visitor {
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}
// 具体访问者
public class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA elementA) {
System.out.println("访问者处理 A 元素");
elementA.operationA();
}
@Override
public void visit(ConcreteElementB elementB) {
System.out.println("访问者处理 B 元素");
elementB.operationB();
}
}
// 对象结构
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void add(Element e) { elements.add(e); }
public void remove(Element e) { elements.remove(e); }
public void accept(Visitor visitor) {
for (Element e : elements) {
e.accept(visitor);
}
}
}
// Client
public class Client {
public static void main(String[] args) {
ObjectStructure structure = new ObjectStructure();
structure.add(new ConcreteElementA());
structure.add(new ConcreteElementB());
Visitor visitor = new ConcreteVisitor();
structure.accept(visitor);
}
}
UML类图
classDiagram
class Element {
<<interface>>
+accept(visitor: Visitor)
}
class ConcreteElementA {
+accept(visitor: Visitor)
+operationA()
}
class ConcreteElementB {
+accept(visitor: Visitor)
+operationB()
}
class Visitor {
<<interface>>
+visit(elementA: ConcreteElementA)
+visit(elementB: ConcreteElementB)
}
class ConcreteVisitor {
+visit(elementA: ConcreteElementA)
+visit(elementB: ConcreteElementB)
}
class ObjectStructure {
-elements: List~Element~
+add(e: Element)
+remove(e: Element)
+accept(visitor: Visitor)
}
Element <|.. ConcreteElementA
Element <|.. ConcreteElementB
Visitor <|.. ConcreteVisitor
ConcreteElementA --> Visitor : accept
ConcreteElementB --> Visitor : accept
ObjectStructure "1" o-- "*" Element : contains