feat: 重写装饰者模式
This commit is contained in:
parent
b577e71956
commit
e27497157c
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
|
@ -311,4 +311,311 @@ SisterObserver 接受到消息:需要和妹妹说点悄悄话,将女朋友
|
|||
- 抽象组件:一般是最原始、最基础的对象。
|
||||
- 具体组件:一般是最原始最基础的实现对象,可以有多个(只是数量不多),可以大致看下`InputStream`UML结构图。
|
||||
- 装饰角色:继承或者实现**抽象组件**这是最关键的地方。
|
||||
- 具体装饰角色:可以有多个实现或者继承**装饰角色**。
|
||||
- 具体装饰角色:可以有多个实现或者继承**装饰角色**。
|
||||
|
||||
### 简单示例
|
||||
|
||||
需要做一个抽象的相机功能,相机包含拍照功能(这是肯定的),之后随着业务需求要求相机有美颜功能,在这之后还要有滤镜功能,客户还需要延迟摄影功能。
|
||||
|
||||
![image-20250201185356903](./images/设计模式-v2/image-20250201185356903.png)
|
||||
|
||||
#### 代码实现
|
||||
|
||||
1. 需要定义根组件(Component)
|
||||
|
||||
2. 制作最原始的拍照功能,实现根组件
|
||||
3. 制作延迟摄影,实现根组件
|
||||
4. 作为相机之外的功能(美颜),需要定义装饰角色方便为以后的组件进行扩展
|
||||
5. 继承或者实现(装饰者角色),完成美颜
|
||||
6. 继承或者实现(装饰者角色),完成滤镜
|
||||
|
||||
```java
|
||||
public class CameraDemo {
|
||||
public static void main(String[] args) {
|
||||
TakePhotoCamera takePhotoCamera = new TakePhotoCamera();
|
||||
takePhotoCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
BeautyCamera beautyCamera = new BeautyCamera(takePhotoCamera);
|
||||
beautyCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
FilterCamera filterCamera = new FilterCamera(beautyCamera);
|
||||
filterCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
TimerCamera timerCamera = new TimerCamera();
|
||||
timerCamera.setTime(2);
|
||||
timerCamera.operation();
|
||||
filterCamera = new FilterCamera(beautyCamera);
|
||||
filterCamera.operation();
|
||||
}
|
||||
|
||||
// 相机功能
|
||||
interface Camera {
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
void operation();
|
||||
}
|
||||
|
||||
// 相机装饰者角色
|
||||
static abstract class CameraDecorator implements Camera {
|
||||
Camera camera;
|
||||
|
||||
public CameraDecorator(Camera camera) {
|
||||
this.camera = camera;
|
||||
}
|
||||
}
|
||||
|
||||
// 相机拍照
|
||||
static class TakePhotoCamera implements Camera {
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("相机拍照。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 相机功能
|
||||
static class BeautyCamera extends CameraDecorator {
|
||||
|
||||
public BeautyCamera(Camera camera) {
|
||||
super(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
camera.operation();
|
||||
System.out.println("美颜功能。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 滤镜效果
|
||||
static class FilterCamera extends CameraDecorator {
|
||||
|
||||
public FilterCamera(Camera camera) {
|
||||
super(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
camera.operation();
|
||||
System.out.println("滤镜效果。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 实现相机延迟功能
|
||||
@Setter
|
||||
static class TimerCamera implements Camera {
|
||||
|
||||
// 延迟时间
|
||||
private Integer time = 0;
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("开始拍照,延迟时间:" + time + "s");
|
||||
try {
|
||||
Thread.sleep(time * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 运行结果:
|
||||
|
||||
```java
|
||||
相机拍照。。。
|
||||
|
||||
-----------------分割线-----------------
|
||||
|
||||
相机拍照。。。
|
||||
美颜功能。。。
|
||||
|
||||
-----------------分割线-----------------
|
||||
|
||||
相机拍照。。。
|
||||
美颜功能。。。
|
||||
滤镜效果。。。
|
||||
|
||||
-----------------分割线-----------------
|
||||
|
||||
开始拍照,延迟时间:2s
|
||||
相机拍照。。。
|
||||
美颜功能。。。
|
||||
滤镜效果。。。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 命令模式
|
||||
|
||||
**Command**:定义执行请求的接口(或抽象类)。
|
||||
|
||||
**ConcreteCommand**:实现命令接口并具体化执行请求的过程,通常还会持有接收者对象。
|
||||
|
||||
**Receiver**:具体的对象,完成实际的操作任务。
|
||||
|
||||
**Invoker**:调用命令的对象,触发命令的执行。
|
||||
|
||||
**Client**:客户端,负责创建并配置命令对象,将命令与接收者绑定,并传递给调用者执行。
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 单例模式
|
||||
|
||||
### 懒汉模式
|
||||
|
||||
#### 双重检查锁定(DCL)
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 静态内部类方式
|
||||
|
||||
利用 **静态内部类**(饿汉式)的特性来实现懒汉模式,并且可以保证线程安全。这种方式只有在调用 `getInstance()` 时才会加载内部类,从而实现懒加载。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
private Singleton() {
|
||||
// 构造函数私有化
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final Singleton INSTANCE = new Singleton();
|
||||
}
|
||||
|
||||
public static Singleton getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 适用场景
|
||||
|
||||
- 如果单例对象比较重,且只在程序中某些特定情况下才使用,懒汉模式可以带来性能优势。
|
||||
- 在低并发环境或单线程环境下,懒汉模式使用较为简单,不会有多线程安全问题。
|
||||
- 对于高并发且需要频繁访问单例的场景,推荐使用**静态内部类**或**饿汉模式**来避免懒汉模式可能带来的性能问题。
|
||||
|
||||
#### 总结
|
||||
|
||||
懒汉模式有时为了延迟初始化而牺牲了性能,特别是在多线程环境下。为了保证线程安全,可以采用双重检查锁定(DCL)或静态内部类的方式,而**静态内部类方式是最推荐的方式**
|
||||
,它避免了同步开销,同时也能确保线程安全。
|
||||
|
||||
- **优点**:
|
||||
1. 延迟加载,节省资源。
|
||||
2. 内存优化,只有在需要时才实例化。
|
||||
3. 减少不必要的初始化开销。
|
||||
- **缺点**:
|
||||
1. 传统懒汉模式线程不安全(多个线程可能会创建多个实例)。
|
||||
2. 使用同步机制会有性能开销,特别是在多线程环境下。
|
||||
3. 代码复杂性较高,容易引入错误。
|
||||
4. 不适合高并发场景,特别是频繁访问时会影响性能。
|
||||
|
||||
### 饿汉模式
|
||||
|
||||
**饿汉模式**(Eager Initialization)是单例模式的一种实现方式,在该方式中,单例实例在类加载时就已经创建完成,而不是在首次使用时才创建。换句话说,**饿汉模式**
|
||||
的单例实例在类被加载时就会立即初始化,确保了单例模式的唯一性。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
|
||||
// 在类加载时就初始化单例对象
|
||||
private static final Singleton INSTANCE = new Singleton();
|
||||
|
||||
// 私有构造函数,防止外部通过 new 创建实例
|
||||
private Singleton() {
|
||||
}
|
||||
|
||||
// 提供全局访问点
|
||||
public static Singleton getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 适用场景
|
||||
|
||||
- **简单应用**:适合没有延迟初始化需求的小型应用,或者单例对象的创建非常轻量,不会影响系统性能的场景。
|
||||
- **实例化不耗费太多资源**:如果单例对象的初始化过程非常轻量级且无须延迟初始化,可以使用饿汉模式。
|
||||
- **类加载顺序固定**:如果不在乎单例对象在启动时是否初始化,且单例对象的初始化过程没有严重性能损失,可以选择饿汉模式。
|
||||
|
||||
#### 总结
|
||||
|
||||
- **优点**:简单、线程安全、性能高(没有锁机制)、实现方便。
|
||||
- **缺点**:不支持延迟加载、可能会浪费资源(如果单例对象不常用时)。
|
||||
|
||||
饿汉模式是单例模式中最简单的实现方式,适用于大多数情况下单例对象的创建开销较小,且不需要延迟初始化的场景。如果单例对象的创建非常轻量且不依赖于后期加载时的资源,饿汉模式是一个不错的选择。
|
||||
|
||||
### 枚举类型实现
|
||||
|
||||
**枚举类型实现单例模式**(Enum Singleton)是实现单例模式的另一种方式,优点是更加简洁、可靠,并且避免了许多常见的单例实现方式(如懒汉模式和饿汉模式)可能出现的问题。使用枚举类型的单例实现方式自
|
||||
**Java 5** 引入以来,已经成为了最推荐的单例模式实现方式之一。
|
||||
|
||||
**当你不需要懒加载或延迟初始化时,使用枚举实现单例模式是最理想的选择。**
|
||||
|
||||
```java
|
||||
public enum Singleton {
|
||||
|
||||
// 唯一实例
|
||||
INSTANCE;
|
||||
|
||||
// 可以添加其他的方法
|
||||
public void someMethod() {
|
||||
System.out.println("This is a singleton instance method.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// 获取单例对象
|
||||
Singleton singleton = Singleton.INSTANCE;
|
||||
|
||||
// 调用单例方法
|
||||
singleton.someMethod();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
444
README/设计模式.md
444
README/设计模式.md
|
@ -1,142 +1,5 @@
|
|||
# 设计模式
|
||||
|
||||
## 单例模式
|
||||
|
||||
### 懒汉模式
|
||||
|
||||
#### 双重检查锁定(DCL)
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 静态内部类方式
|
||||
|
||||
利用 **静态内部类**(饿汉式)的特性来实现懒汉模式,并且可以保证线程安全。这种方式只有在调用 `getInstance()` 时才会加载内部类,从而实现懒加载。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
private Singleton() {
|
||||
// 构造函数私有化
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final Singleton INSTANCE = new Singleton();
|
||||
}
|
||||
|
||||
public static Singleton getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 适用场景
|
||||
|
||||
- 如果单例对象比较重,且只在程序中某些特定情况下才使用,懒汉模式可以带来性能优势。
|
||||
- 在低并发环境或单线程环境下,懒汉模式使用较为简单,不会有多线程安全问题。
|
||||
- 对于高并发且需要频繁访问单例的场景,推荐使用**静态内部类**或**饿汉模式**来避免懒汉模式可能带来的性能问题。
|
||||
|
||||
#### 总结
|
||||
|
||||
懒汉模式有时为了延迟初始化而牺牲了性能,特别是在多线程环境下。为了保证线程安全,可以采用双重检查锁定(DCL)或静态内部类的方式,而**静态内部类方式是最推荐的方式**
|
||||
,它避免了同步开销,同时也能确保线程安全。
|
||||
|
||||
- **优点**:
|
||||
1. 延迟加载,节省资源。
|
||||
2. 内存优化,只有在需要时才实例化。
|
||||
3. 减少不必要的初始化开销。
|
||||
- **缺点**:
|
||||
1. 传统懒汉模式线程不安全(多个线程可能会创建多个实例)。
|
||||
2. 使用同步机制会有性能开销,特别是在多线程环境下。
|
||||
3. 代码复杂性较高,容易引入错误。
|
||||
4. 不适合高并发场景,特别是频繁访问时会影响性能。
|
||||
|
||||
### 饿汉模式
|
||||
|
||||
**饿汉模式**(Eager Initialization)是单例模式的一种实现方式,在该方式中,单例实例在类加载时就已经创建完成,而不是在首次使用时才创建。换句话说,**饿汉模式**
|
||||
的单例实例在类被加载时就会立即初始化,确保了单例模式的唯一性。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
|
||||
// 在类加载时就初始化单例对象
|
||||
private static final Singleton INSTANCE = new Singleton();
|
||||
|
||||
// 私有构造函数,防止外部通过 new 创建实例
|
||||
private Singleton() {
|
||||
}
|
||||
|
||||
// 提供全局访问点
|
||||
public static Singleton getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 适用场景
|
||||
|
||||
- **简单应用**:适合没有延迟初始化需求的小型应用,或者单例对象的创建非常轻量,不会影响系统性能的场景。
|
||||
- **实例化不耗费太多资源**:如果单例对象的初始化过程非常轻量级且无须延迟初始化,可以使用饿汉模式。
|
||||
- **类加载顺序固定**:如果不在乎单例对象在启动时是否初始化,且单例对象的初始化过程没有严重性能损失,可以选择饿汉模式。
|
||||
|
||||
#### 总结
|
||||
|
||||
- **优点**:简单、线程安全、性能高(没有锁机制)、实现方便。
|
||||
- **缺点**:不支持延迟加载、可能会浪费资源(如果单例对象不常用时)。
|
||||
|
||||
饿汉模式是单例模式中最简单的实现方式,适用于大多数情况下单例对象的创建开销较小,且不需要延迟初始化的场景。如果单例对象的创建非常轻量且不依赖于后期加载时的资源,饿汉模式是一个不错的选择。
|
||||
|
||||
### 枚举类型实现
|
||||
|
||||
**枚举类型实现单例模式**(Enum Singleton)是实现单例模式的另一种方式,优点是更加简洁、可靠,并且避免了许多常见的单例实现方式(如懒汉模式和饿汉模式)可能出现的问题。使用枚举类型的单例实现方式自
|
||||
**Java 5** 引入以来,已经成为了最推荐的单例模式实现方式之一。
|
||||
|
||||
**当你不需要懒加载或延迟初始化时,使用枚举实现单例模式是最理想的选择。**
|
||||
|
||||
```java
|
||||
public enum Singleton {
|
||||
|
||||
// 唯一实例
|
||||
INSTANCE;
|
||||
|
||||
// 可以添加其他的方法
|
||||
public void someMethod() {
|
||||
System.out.println("This is a singleton instance method.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// 获取单例对象
|
||||
Singleton singleton = Singleton.INSTANCE;
|
||||
|
||||
// 调用单例方法
|
||||
singleton.someMethod();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 总结
|
||||
|
||||
枚举类型实现单例模式是非常推荐的做法,尤其是在 Java 5 及以后的版本。它简单、线程安全、避免了反射和序列化带来的问题,且保证了单例模式的正确性。对于绝大多数的单例模式实现需求,枚举类型是最安全、最简洁、最优雅的解决方案。
|
||||
|
@ -374,310 +237,3 @@ public class Client {
|
|||
- **工厂方法模式**:通过子类来决定产品的创建,适合产品种类较多时,且产品可能会变化。
|
||||
- **抽象工厂模式**:提供多个相关的产品的创建接口,适合需要创建一系列相关产品的场景。
|
||||
|
||||
## 观察者模式
|
||||
|
||||
观察者模式是一种行为设计模式,它允许一个对象(被观察者)在其状态发生变化时,自动通知所有依赖于它的对象(观察者),而不需要知道这些观察者的具体细节。其主要思想是实现“低耦合”,即对象之间的关系通过接口进行松散连接。为了避免使用过时的类,我们可以手动实现观察者模式。我们需要定义一个“观察者”接口和一个“被观察者”接口,并在被观察者中维护一个观察者的列表,通知观察者更新状态。
|
||||
|
||||
![image-20250131222844877](./images/设计模式/image-20250131222844877.png)
|
||||
|
||||
![image-20250131222858501](./images/设计模式/image-20250131222858501.png)
|
||||
|
||||
观察者模式在以下场景中非常适用:
|
||||
|
||||
- **事件驱动的系统**:如 GUI 事件处理、用户交互。
|
||||
- **发布/订阅机制**:如新闻推送、社交媒体更新。
|
||||
- **实时数据监控**:如股票、天气、系统监控等。
|
||||
- **模型-视图-控制器(MVC)**:使视图根据模型的变化自动更新。
|
||||
- **实时更新场景**:如游戏开发中的实时数据变化通知。
|
||||
|
||||
### 观察者
|
||||
|
||||
#### 观察者接口
|
||||
|
||||
```java
|
||||
/**
|
||||
* 观察者接口
|
||||
*/
|
||||
public interface Observer {
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*
|
||||
* @param temperature 温度
|
||||
* @param humidity 湿度
|
||||
* @param pressure 气压
|
||||
*/
|
||||
void update(float temperature, float humidity, float pressure);
|
||||
}
|
||||
```
|
||||
|
||||
#### 观察者的实现
|
||||
|
||||
```java
|
||||
public class Observer1 implements Observer {
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*
|
||||
* @param temperature 温度
|
||||
* @param humidity 湿度
|
||||
* @param pressure 气压
|
||||
*/
|
||||
@Override
|
||||
public void update(float temperature, float humidity, float pressure) {
|
||||
System.out.println("Observer1 显示数据:temperature = " + temperature + ";humidity = " + humidity);
|
||||
}
|
||||
}
|
||||
|
||||
public class Observer2 implements Observer {
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*
|
||||
* @param temperature 温度
|
||||
* @param humidity 湿度
|
||||
* @param pressure 气压
|
||||
*/
|
||||
@Override
|
||||
public void update(float temperature, float humidity, float pressure) {
|
||||
System.out.println("Observer2 显示数据:temperature = " + temperature + ";humidity = " + humidity);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class Observer3 implements Observer {
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*
|
||||
* @param temperature 温度
|
||||
* @param humidity 湿度
|
||||
* @param pressure 气压
|
||||
*/
|
||||
@Override
|
||||
public void update(float temperature, float humidity, float pressure) {
|
||||
System.out.println("Observer3 显示数据:temperature = " + temperature + ";humidity = " + humidity);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 主题
|
||||
|
||||
#### 主体接口
|
||||
|
||||
```java
|
||||
/**
|
||||
* 被观察者接口
|
||||
*/
|
||||
public interface Subject {
|
||||
void registerObserver(Observer observer);
|
||||
|
||||
void removeObserver(Observer observer);
|
||||
|
||||
void notifyObservers();
|
||||
}
|
||||
```
|
||||
|
||||
#### 主体实现
|
||||
|
||||
```java
|
||||
import cn.bunny.pattern3.demo1.observer.Observer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 被观察者类
|
||||
*/
|
||||
public class WeatherStationSubject implements Subject {
|
||||
private final List<Observer> observers = new ArrayList<>();
|
||||
private float temperature;
|
||||
private float humidity;
|
||||
private float pressure;
|
||||
|
||||
@Override
|
||||
public void registerObserver(Observer observer) {
|
||||
observers.add(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeObserver(Observer observer) {
|
||||
observers.remove(observer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyObservers() {
|
||||
for (Observer observer : observers) {
|
||||
observer.update(temperature, humidity, pressure);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTemperature(float temperature, float humidity, float pressure) {
|
||||
this.temperature = temperature;
|
||||
this.humidity = humidity;
|
||||
this.pressure = pressure;
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 运行
|
||||
|
||||
```java
|
||||
import cn.bunny.pattern3.demo1.observer.Observer;
|
||||
import cn.bunny.pattern3.demo1.observer.Observer1;
|
||||
import cn.bunny.pattern3.demo1.observer.Observer2;
|
||||
import cn.bunny.pattern3.demo1.observer.Observer3;
|
||||
import cn.bunny.pattern3.demo1.subject.WeatherStationSubject;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
WeatherStationSubject weatherStationSubject = new WeatherStationSubject();
|
||||
Observer observer1 = new Observer1();
|
||||
Observer observer2 = new Observer2();
|
||||
Observer observer3 = new Observer3();
|
||||
|
||||
// 注册观察者
|
||||
weatherStationSubject.registerObserver(observer1);
|
||||
weatherStationSubject.registerObserver(observer2);
|
||||
weatherStationSubject.registerObserver(observer3);
|
||||
|
||||
// 更新天气温度,观察者会收到通知
|
||||
weatherStationSubject.setTemperature(25.0f, 25.0f, 25.0f);
|
||||
weatherStationSubject.setTemperature(30.0f, 30.0f, 30.0f);
|
||||
|
||||
// 移出观察者1
|
||||
weatherStationSubject.removeObserver(observer1);
|
||||
|
||||
// 更新天气温度,观察者会收到通知
|
||||
System.out.println("--------------------------");
|
||||
weatherStationSubject.setTemperature(44.0f, 44.0f, 44.0f);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
![image-20250131223737965](./images/设计模式/image-20250131223737965.png)
|
||||
|
||||
## 装饰者模式
|
||||
|
||||
装饰器模式是一种结构型设计模式,允许在不修改对象代码的前提下,动态地给一个对象添加额外的功能。它通过“包装”原始对象,使用一个或多个装饰器类对其功能进行增强或修改。
|
||||
|
||||
简单来说,装饰器模式通过“装饰”原有对象来扩展功能,而不是通过继承来修改对象的行为。
|
||||
|
||||
适用的场景包括 I/O 流处理、GUI 组件、日志功能、权限管理、Web 请求处理等。在这些场景中,装饰器模式帮助程序员按需扩展功能,而不会破坏现有代码的结构。
|
||||
|
||||
**汽车案例**
|
||||
|
||||
假设你有一辆普通的车(**基本功能**),如果你想让这辆车变成运动型车或豪华车(**添加新功能**),你可以将这辆车包装在不同的装饰器中。例如:
|
||||
|
||||
- **基本车**:一辆普通的车。
|
||||
- **运动型车**:在基本车上增加运动功能,比如加速性能、运动座椅等。
|
||||
- **豪华车**:在基本车上增加奢华功能,如高档内饰、音响系统等。
|
||||
|
||||
通过使用装饰器模式,你可以自由组合这些功能(运动型 + 豪华型),而不需要修改原有的 `Car` 类。
|
||||
|
||||
![image-20250201105537485](./images/设计模式/image-20250201105537485.png)
|
||||
|
||||
**相机案例**
|
||||
|
||||
![image-20250201105612849](./images/设计模式/image-20250201105612849.png)
|
||||
|
||||
### 装饰器模式的结构
|
||||
|
||||
1. **Component(组件接口)**:定义了被装饰对象的共同行为,通常是一个接口或抽象类。
|
||||
2. **ConcreteComponent(具体组件)**:实现了 `Component` 接口,表示被装饰的对象。
|
||||
3. **Decorator(装饰器)**:实现 `Component` 接口,并持有一个 `Component` 对象,目的是对其进行包装。
|
||||
4. **ConcreteDecorator(具体装饰器)**:扩展了 `Decorator` 类,为 `Component` 添加额外的功能。
|
||||
|
||||
#### 优点
|
||||
|
||||
1. **灵活性**:装饰器模式可以通过动态地组合多个装饰器来实现功能的拓展,而不需要修改现有类或创建大量的子类。
|
||||
2. **遵循开放-封闭原则**:类对扩展开放,对修改封闭。你可以通过装饰器添加新功能,而无需修改现有的类代码。
|
||||
3. **功能复用**:装饰器模式支持组合多个装饰器,通过不同的装饰器组合可以重用已有的功能。
|
||||
4. **避免类膨胀**:与继承不同,装饰器模式避免了大量的子类创建,能够更灵活地对对象功能进行增强。
|
||||
|
||||
#### 缺点
|
||||
|
||||
1. **增加复杂性**:由于需要创建多个装饰器类,系统的结构可能变得更加复杂,维护和理解装饰器链条可能变得较为困难。
|
||||
2. **多层装饰会导致性能开销**:装饰器模式通常会创建多个小对象进行嵌套包装,导致性能开销增加,尤其在装饰器链条很长时。
|
||||
3. **难以管理装饰器的组合**:如果装饰器有依赖关系或需要特定的顺序才能正确工作,那么组合多个装饰器可能会变得更加困难,增加了使用的难度。
|
||||
|
||||
### 相机
|
||||
|
||||
#### 相机接口
|
||||
|
||||
```java
|
||||
public interface Camera {
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
void operation();
|
||||
}
|
||||
```
|
||||
|
||||
#### 相机实现
|
||||
|
||||
```java
|
||||
public class TakePhotoCamera implements Camera {
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("拍照。。。");
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class CameraDecorator implements Camera {
|
||||
|
||||
final Camera camera;
|
||||
|
||||
public CameraDecorator(Camera camera) {
|
||||
this.camera = camera;
|
||||
}
|
||||
}
|
||||
|
||||
public class FilterCameraDecorator extends CameraDecorator {
|
||||
public FilterCameraDecorator(Camera camera) {
|
||||
super(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
camera.operation();
|
||||
System.out.println("滤镜功能。。。");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 运行
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("------------------执行简单的拍照-------------------");
|
||||
|
||||
TakePhotoCamera takePhotoCamera = new TakePhotoCamera();
|
||||
takePhotoCamera.operation();
|
||||
|
||||
System.out.println("-------------------需要美颜功能------------------");
|
||||
|
||||
BeautyCameraDecorator beautyCameraDecorator = new BeautyCameraDecorator(takePhotoCamera);
|
||||
beautyCameraDecorator.operation();
|
||||
|
||||
System.out.println("-------------------需要美颜功能之后滤镜------------------");
|
||||
|
||||
FilterCameraDecorator filterCameraDecorator = new FilterCameraDecorator(beautyCameraDecorator);
|
||||
filterCameraDecorator.operation();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
![image-20250201135138918](./images/设计模式/image-20250201135138918.png)
|
||||
|
||||
## 命令模式
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package cn.bunny.pattern4.demo3;
|
||||
|
||||
import lombok.Setter;
|
||||
|
||||
public class CameraDemo {
|
||||
public static void main(String[] args) {
|
||||
TakePhotoCamera takePhotoCamera = new TakePhotoCamera();
|
||||
takePhotoCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
BeautyCamera beautyCamera = new BeautyCamera(takePhotoCamera);
|
||||
beautyCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
FilterCamera filterCamera = new FilterCamera(beautyCamera);
|
||||
filterCamera.operation();
|
||||
|
||||
System.out.println("\n-----------------分割线-----------------\n");
|
||||
|
||||
TimerCamera timerCamera = new TimerCamera();
|
||||
timerCamera.setTime(2);
|
||||
timerCamera.operation();
|
||||
filterCamera = new FilterCamera(beautyCamera);
|
||||
filterCamera.operation();
|
||||
}
|
||||
|
||||
// 相机功能
|
||||
interface Camera {
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
void operation();
|
||||
}
|
||||
|
||||
// 相机装饰者角色
|
||||
static abstract class CameraDecorator implements Camera {
|
||||
Camera camera;
|
||||
|
||||
public CameraDecorator(Camera camera) {
|
||||
this.camera = camera;
|
||||
}
|
||||
}
|
||||
|
||||
// 相机拍照
|
||||
static class TakePhotoCamera implements Camera {
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("相机拍照。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 相机功能
|
||||
static class BeautyCamera extends CameraDecorator {
|
||||
|
||||
public BeautyCamera(Camera camera) {
|
||||
super(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
camera.operation();
|
||||
System.out.println("美颜功能。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 滤镜效果
|
||||
static class FilterCamera extends CameraDecorator {
|
||||
|
||||
public FilterCamera(Camera camera) {
|
||||
super(camera);
|
||||
}
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
camera.operation();
|
||||
System.out.println("滤镜效果。。。");
|
||||
}
|
||||
}
|
||||
|
||||
// 实现相机延迟功能
|
||||
@Setter
|
||||
static class TimerCamera implements Camera {
|
||||
|
||||
// 延迟时间
|
||||
private Integer time = 0;
|
||||
|
||||
/**
|
||||
* 相机操作
|
||||
*/
|
||||
@Override
|
||||
public void operation() {
|
||||
System.out.println("开始拍照,延迟时间:" + time + "s");
|
||||
try {
|
||||
Thread.sleep(time * 1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue