feat: 重写策略模式

This commit is contained in:
Bunny 2025-02-01 17:36:49 +08:00
parent 503cdee2a0
commit fb7360c387
28 changed files with 463 additions and 207 deletions

View File

@ -143,7 +143,15 @@ public class Main {
## 工厂模式
工厂模式Factory Pattern是创建型设计模式的一种它提供了一种创建对象的方式而不需要暴露具体的类实例化过程。工厂模式有三种常见的实现方式
工厂模式Factory Pattern是创建型设计模式的一种它提供了一种创建对象的方式而不需要暴露具体的类实例化过程。
工厂模式适用于以下场景:
- **对象创建逻辑复杂**:当对象的创建过程比较复杂,包含多个初始化步骤时。
- **类的创建与实现解耦**:客户端只关心产品的接口,而不关心具体实现。
- **动态选择不同类型的对象**:需要根据不同条件动态选择创建的对象类型。
- **产品种类变化频繁**:产品的类型变化较多时,使用工厂模式能使扩展更加灵活。
- **避免客户端直接实例化**:通过工厂封装对象的创建过程,减少客户端与具体实现的耦合。
### 1. **简单工厂模式Simple Factory Pattern**
@ -366,202 +374,23 @@ public class Client {
- **工厂方法模式**:通过子类来决定产品的创建,适合产品种类较多时,且产品可能会变化。
- **抽象工厂模式**:提供多个相关的产品的创建接口,适合需要创建一系列相关产品的场景。
## 策略模式
![image-20250131223259043](./images/设计模式/image-20250131223259043.png)
![image-20250131223315954](./images/设计模式/image-20250131223315954.png)
我们通过策略模式来实现鸭子的飞行和叫声行为,使得它们可以在运行时灵活替换。
### 飞行行为
#### 飞行接口
```java
public interface FlyBehavior {
/**
* 飞的样子
*/
void fly();
}
```
#### 飞行实现
```java
public class FlyNoWay implements FlyBehavior {
/**
* 飞的样子
*/
@Override
public void fly() {
System.out.println("不能飞。。。");
}
}
public class FlyWithWings implements FlyBehavior {
/**
* 飞的样子
*/
@Override
public void fly() {
System.out.println("可以飞。。。");
}
}
```
### 叫的行为
#### 叫的接口
```java
public interface QuackBehavior {
/**
* 怎么叫的
*/
void quack();
}
```
#### 叫的实现
```java
public class MuteQuack implements QuackBehavior {
/**
* 怎么叫的
*/
@Override
public void quack() {
System.out.println("不会叫...");
}
}
public class Quack implements QuackBehavior {
/**
* 怎么叫的
*/
@Override
public void quack() {
System.out.println("鸭子叫。。。");
}
}
```
### 鸭子
```java
@Setter
public abstract class AbstractDuck {
// 设置新的叫声行为
QuackBehavior quackBehavior;
// 设置新的飞行行为
FlyBehavior flyBehavior;
public AbstractDuck() {
}
/**
* 展示什么类型的鸭子
*/
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("鸭子游泳");
}
}
```
#### 鸭子继承
```java
public class ModelDuck extends AbstractDuck {
private final String modelDuck = "橡皮🦆";
public ModelDuck() {
super.setFlyBehavior(new FlyNoWay());
super.quackBehavior = new MuteQuack();
}
/**
* 展示什么类型的鸭子
*/
@Override
public void display() {
System.out.println(modelDuck + "...");
}
/**
*
*/
@Override
public void swim() {
System.out.println(modelDuck + "不会游泳。。。");
}
}
public class WoodDuck extends AbstractDuck {
private final String modelDuck = "木头🦆";
public WoodDuck() {
super.flyBehavior = new FlyNoWay();
super.quackBehavior = new MuteQuack();
}
/**
* 展示什么类型的鸭子
*/
@Override
public void display() {
System.out.println(modelDuck + "...");
}
}
```
### 运行
```java
public class Main {
public static void main(String[] args) {
ModelDuck modelDuck = new ModelDuck();
modelDuck.display();
modelDuck.performFly();
modelDuck.performQuack();
modelDuck.swim();
System.out.println("--------------------------------");
AbstractDuck woodDuck = new WoodDuck();
woodDuck.display();
woodDuck.performFly();
woodDuck.performQuack();
woodDuck.swim();
}
}
```
![image-20250131224206984](./images/设计模式/image-20250131224206984.png)
## 观察者模式
观察者模式是一种行为设计模式,它允许一个对象(被观察者)在其状态发生变化时,自动通知所有依赖于它的对象(观察者),而不需要知道这些观察者的具体细节。其主要思想是实现“低耦合”,即对象之间的关系通过接口进行松散连接。
观察者模式是一种行为设计模式,它允许一个对象(被观察者)在其状态发生变化时,自动通知所有依赖于它的对象(观察者),而不需要知道这些观察者的具体细节。其主要思想是实现“低耦合”,即对象之间的关系通过接口进行松散连接。为了避免使用过时的类,我们可以手动实现观察者模式。我们需要定义一个“观察者”接口和一个“被观察者”接口,并在被观察者中维护一个观察者的列表,通知观察者更新状态。
![image-20250131222844877](./images/设计模式/image-20250131222844877.png)
![image-20250131222858501](./images/设计模式/image-20250131222858501.png)
为了避免使用过时的类,我们可以手动实现观察者模式。我们需要定义一个“观察者”接口和一个“被观察者”接口,并在被观察者中维护一个观察者的列表,通知观察者更新状态。
观察者模式在以下场景中非常适用:
- **事件驱动的系统**:如 GUI 事件处理、用户交互。
- **发布/订阅机制**:如新闻推送、社交媒体更新。
- **实时数据监控**:如股票、天气、系统监控等。
- **模型-视图-控制器MVC**:使视图根据模型的变化自动更新。
- **实时更新场景**:如游戏开发中的实时数据变化通知。
### 观察者
@ -737,6 +566,8 @@ public class Main {
简单来说,装饰器模式通过“装饰”原有对象来扩展功能,而不是通过继承来修改对象的行为。
适用的场景包括 I/O 流处理、GUI 组件、日志功能、权限管理、Web 请求处理等。在这些场景中,装饰器模式帮助程序员按需扩展功能,而不会破坏现有代码的结构。
**汽车案例**
假设你有一辆普通的车(**基本功能**),如果你想让这辆车变成运动型车或豪华车(**添加新功能**),你可以将这辆车包装在不同的装饰器中。例如:
@ -849,3 +680,6 @@ public class Main {
```
![image-20250201135138918](./images/设计模式/image-20250201135138918.png)
## 命令模式

View File

@ -1,8 +1,8 @@
package cn.bunny.pattern2;
package cn.bunny.pattern2.demo1;
import cn.bunny.pattern2.duck.AbstractDuck;
import cn.bunny.pattern2.duck.ModelDuck;
import cn.bunny.pattern2.duck.WoodDuck;
import cn.bunny.pattern2.demo1.duck.AbstractDuck;
import cn.bunny.pattern2.demo1.duck.ModelDuck;
import cn.bunny.pattern2.demo1.duck.WoodDuck;
public class Main {
public static void main(String[] args) {

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.fly;
package cn.bunny.pattern2.demo1.behavior.fly;
public interface FlyBehavior {
/**

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.fly;
package cn.bunny.pattern2.demo1.behavior.fly;
public class FlyNoWay implements FlyBehavior {
/**

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.fly;
package cn.bunny.pattern2.demo1.behavior.fly;
public class FlyWithWings implements FlyBehavior {
/**

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.quack;
package cn.bunny.pattern2.demo1.behavior.quack;
public class MuteQuack implements QuackBehavior {
/**

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.quack;
package cn.bunny.pattern2.demo1.behavior.quack;
public class Quack implements QuackBehavior {
/**

View File

@ -1,4 +1,4 @@
package cn.bunny.pattern2.behavior.quack;
package cn.bunny.pattern2.demo1.behavior.quack;
public interface QuackBehavior {
/**

View File

@ -1,7 +1,7 @@
package cn.bunny.pattern2.duck;
package cn.bunny.pattern2.demo1.duck;
import cn.bunny.pattern2.behavior.fly.FlyBehavior;
import cn.bunny.pattern2.behavior.quack.QuackBehavior;
import cn.bunny.pattern2.demo1.behavior.fly.FlyBehavior;
import cn.bunny.pattern2.demo1.behavior.quack.QuackBehavior;
import lombok.Setter;
@Setter

View File

@ -1,7 +1,7 @@
package cn.bunny.pattern2.duck;
package cn.bunny.pattern2.demo1.duck;
import cn.bunny.pattern2.behavior.fly.FlyNoWay;
import cn.bunny.pattern2.behavior.quack.MuteQuack;
import cn.bunny.pattern2.demo1.behavior.fly.FlyNoWay;
import cn.bunny.pattern2.demo1.behavior.quack.MuteQuack;
public class ModelDuck extends AbstractDuck {

View File

@ -1,7 +1,7 @@
package cn.bunny.pattern2.duck;
package cn.bunny.pattern2.demo1.duck;
import cn.bunny.pattern2.behavior.fly.FlyNoWay;
import cn.bunny.pattern2.behavior.quack.MuteQuack;
import cn.bunny.pattern2.demo1.behavior.fly.FlyNoWay;
import cn.bunny.pattern2.demo1.behavior.quack.MuteQuack;
public class WoodDuck extends AbstractDuck {

View File

@ -0,0 +1,63 @@
package cn.bunny.pattern2.demo2;
public class BaseStrategy {
public static void main(String[] args) {
// 每一个策略
ConcreteStrategy1 concreteStrategy1 = new ConcreteStrategy1();
ConcreteStrategy2 concreteStrategy2 = new ConcreteStrategy2();
// 执行策略
new Context(concreteStrategy1).doIt();
new Context(concreteStrategy2).doIt();
}
// 基本的策略
public interface Strategy {
/**
* 需要执行的方法
*/
void method();
}
// 具体的策略实现1
public static class ConcreteStrategy1 implements Strategy {
/**
* 需要执行的方法
*/
@Override
public void method() {
System.out.println("具体的策略实现1...");
}
}
// 具体的策略实现2
public static class ConcreteStrategy2 implements Strategy {
/**
* 需要执行的方法
*/
@Override
public void method() {
System.out.println("具体的策略实现2...");
}
}
// 提供上下文
public static class Context {
private final Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* 需要做的事情
*/
public void doIt() {
strategy.method();
}
}
}

View File

@ -0,0 +1,87 @@
package cn.bunny.pattern2.demo3;
import lombok.Setter;
public class GameCharacter {
public static void main(String[] args) {
Character soldier = new Soldier();
soldier.fight();
Character king = new King();
king.setPrimaryWeapon(new AxeWeapon());
king.fight();
}
// 武器接口
interface Weapon {
String function();
}
// 各种武器实现
public static class SwordWeapon implements Weapon {
@Override
public String function() {
return "⚔️ ⚔️ ⚔️";
}
}
public static class AxeWeapon implements Weapon {
@Override
public String function() {
return "🪓 🪓 🪓";
}
}
public static class KnifeWeapon implements Weapon {
@Override
public String function() {
return "🔪 🔪 🔪";
}
}
// 抽象角色类
public abstract static class Character {
String name;
@Setter
private Weapon primaryWeapon;
@Setter
private Weapon subWeapon;
public Character(String name) {
this.name = name;
// 默认武器配置
this.primaryWeapon = new SwordWeapon();
this.subWeapon = new KnifeWeapon();
}
void fight() {
if (primaryWeapon != null && subWeapon != null) {
String primary = primaryWeapon.function();
String sub = subWeapon.function();
System.out.println(name + "" + primary + "" + sub);
} else {
System.out.println(name + "没有武器!");
}
}
}
// 国王角色
public static class King extends Character {
public King() {
super("King");
setPrimaryWeapon(new SwordWeapon());
setSubWeapon(new KnifeWeapon());
}
}
// 士兵角色
public static class Soldier extends Character {
public Soldier() {
super("Soldier");
setPrimaryWeapon(new AxeWeapon());
setSubWeapon(new SwordWeapon());
}
}
}

View File

@ -0,0 +1,12 @@
package cn.bunny.pattern5.demo1;
// 接收者空调
public class AirConditioner {
public void on() {
System.out.println("空调打开了");
}
public void off() {
System.out.println("空调关闭了");
}
}

View File

@ -0,0 +1,36 @@
package cn.bunny.pattern5.demo1;
import cn.bunny.pattern5.demo1.command.*;
public class Main {
public static void main(String[] args) {
// 创建接收者对象
TV tv = new TV();
AirConditioner airConditioner = new AirConditioner();
// 创建命令对象并绑定接收者
Command tvOn = new TVOnCommand(tv);
Command tvOff = new TVOffCommand(tv);
Command airConditionerOn = new AirConditionerOnCommand(airConditioner);
Command airConditionerOff = new AirConditionerOffCommand(airConditioner);
// 创建遥控器调用者
RemoteControl remoteControl = new RemoteControl();
// 按钮1打开电视
remoteControl.setCommand(tvOn);
remoteControl.pressButton(); // 输出电视机打开了
// 按钮2关闭电视
remoteControl.setCommand(tvOff);
remoteControl.pressButton(); // 输出电视机关闭了
// 按钮3打开空调
remoteControl.setCommand(airConditionerOn);
remoteControl.pressButton(); // 输出空调打开了
// 按钮4关闭空调
remoteControl.setCommand(airConditionerOff);
remoteControl.pressButton(); // 输出空调关闭了
}
}

View File

@ -0,0 +1,14 @@
package cn.bunny.pattern5.demo1;
import cn.bunny.pattern5.demo1.command.Command;
import lombok.Setter;
// 遥控器调用者
@Setter
public class RemoteControl {
private Command command;
public void pressButton() {
command.execute();
}
}

View File

@ -0,0 +1,14 @@
package cn.bunny.pattern5.demo1;
// 接收者电视机
public class TV {
public void on() {
System.out.println("电视机打开了");
}
public void off() {
System.out.println("电视机关闭了");
}
}

View File

@ -0,0 +1,17 @@
package cn.bunny.pattern5.demo1.command;
import cn.bunny.pattern5.demo1.AirConditioner;
// 具体命令类关闭空调的命令
public class AirConditionerOffCommand implements Command {
private final AirConditioner airConditioner;
public AirConditionerOffCommand(AirConditioner airConditioner) {
this.airConditioner = airConditioner;
}
@Override
public void execute() {
airConditioner.off();
}
}

View File

@ -0,0 +1,17 @@
package cn.bunny.pattern5.demo1.command;
import cn.bunny.pattern5.demo1.AirConditioner;
// 具体命令类打开空调的命令
public class AirConditionerOnCommand implements Command {
private final AirConditioner airConditioner;
public AirConditionerOnCommand(AirConditioner airConditioner) {
this.airConditioner = airConditioner;
}
@Override
public void execute() {
airConditioner.on();
}
}

View File

@ -0,0 +1,5 @@
package cn.bunny.pattern5.demo1.command;
public interface Command {
void execute();
}

View File

@ -0,0 +1,17 @@
package cn.bunny.pattern5.demo1.command;
import cn.bunny.pattern5.demo1.TV;
// 具体命令类关闭电视的命令
public class TVOffCommand implements Command {
private final TV tv;
public TVOffCommand(TV tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.off();
}
}

View File

@ -0,0 +1,17 @@
package cn.bunny.pattern5.demo1.command;
import cn.bunny.pattern5.demo1.TV;
// 具体命令类打开电视的命令
public class TVOnCommand implements Command {
private final TV tv;
public TVOnCommand(TV tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.on();
}
}

View File

@ -0,0 +1,21 @@
package cn.bunny.pattern5.demo2;
/**
* 厨师类
*/
public class Cook {
/**
* 烤羊肉串
*/
public void bakeMutton() {
System.out.println("厨师-烤羊肉串。。。");
}
/**
* 烤鸡翅
*/
public void bakeChickenWing() {
System.out.println("厨师-烤鸡翅。。。");
}
}

View File

@ -0,0 +1,20 @@
package cn.bunny.pattern5.demo2;
import cn.bunny.pattern5.demo2.command.BakeChickenWingCommand;
import cn.bunny.pattern5.demo2.command.BakeMuttonCommand;
public class Main {
public static void main(String[] args) {
Cook cook = new Cook();
Waiter waiter = new Waiter();
// 来点烤鸡翅
waiter.addCommand(new BakeChickenWingCommand(cook));
// 点烤羊肉串
waiter.addCommand(new BakeMuttonCommand(cook));
// 通知厨师去做
waiter.notifyCook();
}
}

View File

@ -0,0 +1,27 @@
package cn.bunny.pattern5.demo2;
import cn.bunny.pattern5.demo2.command.Command;
import java.util.ArrayList;
import java.util.List;
/**
* 服务员
*/
public class Waiter {
private final List<Command> commandList = new ArrayList<>();
public void addCommand(Command command) {
commandList.add(command);
}
/**
* 通知厨师去做
*/
public void notifyCook() {
for (Command command : commandList) {
command.execute();
}
}
}

View File

@ -0,0 +1,18 @@
package cn.bunny.pattern5.demo2.command;
import cn.bunny.pattern5.demo2.Cook;
public class BakeChickenWingCommand extends Command {
public BakeChickenWingCommand(Cook cook) {
super(cook);
}
/**
* 命名的执行方法对具体进行处理
*/
@Override
public void execute() {
cook.bakeChickenWing();
}
}

View File

@ -0,0 +1,18 @@
package cn.bunny.pattern5.demo2.command;
import cn.bunny.pattern5.demo2.Cook;
public class BakeMuttonCommand extends Command {
public BakeMuttonCommand(Cook cook) {
super(cook);
}
/**
* 命名的执行方法对具体进行处理
*/
@Override
public void execute() {
cook.bakeMutton();
}
}

View File

@ -0,0 +1,19 @@
package cn.bunny.pattern5.demo2.command;
import cn.bunny.pattern5.demo2.Cook;
/**
* 命名的抽象可以提供具体的厨师
*/
public abstract class Command {
protected Cook cook;
public Command(Cook cook) {
this.cook = cook;
}
/**
* 命名的执行方法对具体进行处理
*/
public abstract void execute();
}