设计模式通用解释及Java代码用例整理

文章目录

      • 23种设计模式
        • 单例模式(Singleton Pattern)
        • 工厂模式(Factory Pattern)
        • 抽象工厂模式(Abstract Factory Pattern)
        • 建造者模式(Builder Pattern)
        • 原型模式(Prototype Pattern)
        • 适配器模式(Adapter Pattern)
        • 桥接模式(Bridge Pattern)
        • 装饰模式(Decorator Pattern)
        • 代理模式(Proxy Pattern)
        • 外观模式(Facade Pattern)
        • 观察者模式(Observer Pattern)
        • 策略模式(Strategy Pattern)
        • 模板方法模式(Template Method Pattern)
        • 迭代器模式(Iterator Pattern)
        • 组合模式(Composite Pattern)
        • 命令模式(Command Pattern)
        • 备忘录模式(Memento Pattern)
        • 状态模式(State Pattern)
        • 职责链模式(Chain of Responsibility Pattern)
        • 中介者模式(Mediator Pattern)
        • 访问者模式(Visitor Pattern)
        • 解释器模式(Interpreter Pattern)
        • 职责模式(Job Pattern)

设计模式是软件设计中的一些常见模式,它们提供了一种解决特定问题的通用解决方案。这些模式可以帮助开发者更有效地设计和实现软件系统。以下是23种设计模式的通俗解释:

23种设计模式

单例模式(Singleton Pattern)

确保一个类只有一个实例,并提供一个全局访问点。比如,一个系统中只有一个设置或者日志记录的实例。
单例模式在实际应用中非常普遍,例如在数据库连接管理、网络连接管理、缓存管理等场景中。它有助于避免资源的不必要创建,并提供了一个全局访问点来操作该资源。

public class DatabaseConnection {private static final DatabaseConnection INSTANCE = new DatabaseConnection();private DatabaseConnection() {// 初始化数据库连接// 这里可以包括连接池的设置等}public static DatabaseConnection getInstance() {return INSTANCE;}public void executeQuery(String query) {// 执行数据库查询}
}// 使用示例
DatabaseConnection connection = DatabaseConnection.getInstance();
connection.executeQuery("select * from users");// 在这个例子中,DatabaseConnection 类被设计成了单例模式,因此应用程序中所有对数据库的访问都将通过这个唯一的实例来进行,这样可以确保数据库连接的一致性和安全性。
工厂模式(Factory Pattern)

提供一个创建对象的接口,但是由子类决定要实例化的具体类。比如,有一个创建不同类型汽车的工厂,但是用户不需要关心具体实现。
工厂模式就像是有一个专门的工厂,负责生产不同类型的产品。这个工厂有一套标准化的生产流程,但是可以根据客户的需求,生产不同的产品。在软件开发中,这个工厂就是工厂类,它提供了一个接口来创建产品,而具体生产哪种产品则由参数来决定。

例如,有一个汽车工厂,它有一个生产汽车的标准流程。但是,根据客户的需求,这个工厂可以生产不同型号的汽车,比如轿车、SUV或者跑车。客户只需要告诉工厂他们想要哪种汽车,工厂就会生产相应的车型。

// 汽车接口,定义了所有汽车共有的方法
interface Car {void start();void stop();
}// 轿车的具体实现
class Sedan implements Car {@Overridepublic void start() {System.out.println("Sedan started.");}@Overridepublic void stop() {System.out.println("Sedan stopped.");}
}// SUV的具体实现
class Suv implements Car {@Overridepublic void start() {System.out.println("SUV started.");}@Overridepublic void stop() {System.out.println("SUV stopped.");}
}// 工厂类,负责生产不同类型的汽车
class CarFactory {public Car createCar(String type) {if (type.equals("sedan")) {return new Sedan();} else if (type.equals("suv")) {return new Suv();} else {throw new IllegalArgumentException("Invalid car type: " + type);}}
}// 客户端代码
public class FactoryPatternDemo {public static void main(String[] args) {CarFactory carFactory = new CarFactory();Car sedan = carFactory.createCar("sedan");Car suv = carFactory.createCar("suv");sedan.start();sedan.stop();suv.start();suv.stop();}
}### 在这个例子中,CarFactory是工厂类,它有一个createCar方法,可以根据客户(FactoryPatternDemo类)的需求创建不同的汽车(SedanSuv)。客户端只需要调用createCar方法并指定想要的汽车类型,就可以获取到相应的汽车对象,而无需关心汽车的具体实现。
抽象工厂模式(Abstract Factory Pattern)

提供一个创建一系列相关对象的接口,而不用指定它们的具体类。比如,游戏中的不同武器和工具的创建。
这个模式的核心思想是,定义一个抽象的工厂接口,该接口提供了创建产品的抽象方法,而具体的产品类则由子工厂类实现。这样,客户端只需要关心如何获取产品,而不需要关心产品的具体实现。

// AbstractFactory: 抽象工厂接口,它定义了创建产品的方法。
public interface AbstractFactory {ProductA createProductA();ProductB createProductB();// 可以有更多的产品类型
}// ConcreteFactory1: 具体工厂1,它实现了AbstractFactory接口,并提供了具体的创建产品的方法。
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {// 创建ProductA的具体实现return new ProductAImpl1();}@Overridepublic ProductB createProductB() {// 创建ProductB的具体实现return new ProductBImpl1();}
}// ConcreteFactory2: 另一个具体工厂2,它也实现了AbstractFactory接口,并提供了不同的产品实现。
public class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {// 创建ProductA的另一个具体实现return new ProductAImpl2();}@Overridepublic ProductB createProductB() {// 创建ProductB的另一个具体实现return new ProductBImpl2();}
}// ProductA和ProductB: 产品接口,它们是抽象工厂生产的不同产品类型。
public interface ProductA {// 产品A的相关方法
}public interface ProductB {// 产品B的相关方法
}// ProductAImpl1和ProductBImpl1: 产品A和产品B的具体实现。
public class ProductAImpl1 implements ProductA {// 产品A的实现逻辑
}public class ProductBImpl1 implements ProductB {// 产品B的实现逻辑
}// ProductAImpl2和ProductBImpl2: 产品A和产品B的另一个具体实现。
public class ProductAImpl2 implements ProductA {// 产品A的另一个实现逻辑
}public class ProductBImpl2 implements ProductB {// 产品B的另一个实现逻辑
}// 客户端代码
public class Client {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();// 客户端代码使用产品,而不关心它们的实现细节useProduct(productA1, productB1);useProduct(productA2, productB2);}private static void useProduct(ProductA productA, ProductB productB) {// 使用产品A和产品B的方法}
}
// 在这个例子中,Client类创建了两个不同工厂的实例,并使用它们来获取产品。Client类不需要关心产品的具体实现,因为所有的创建逻辑都封装在工厂中。这种模式使得在多个产品族之间切换变得很容易,因为只需要更换工厂即可。
建造者模式(Builder Pattern)

将复杂对象的构建与使用分离,使得构建过程可以独立进行。比如,组装一个复杂的机械设备的过程。这种模式的核心思想是“分而治之”,即将复杂对象的创建过程分解为多个简单的步骤,每个步骤都由一个单独的Builder对象负责。

public class CarBuilder {private Car car = new Car();public CarBuilder setMake(String make) {car.setMake(make);return this;}public CarBuilder setModel(String model) {car.setModel(model);return this;}public CarBuilder setYear(int year) {car.setYear(year);return this;}public CarBuilder setColor(String color) {car.setColor(color);return this;}public Car build() {return car;}
}public class CarConfiguration {@Beanpublic Car getCar() {CarBuilder carBuilder = new CarBuilder();carBuilder.setMake("Toyota").setModel("Corolla").setYear(2023).setColor("Silver");return carBuilder.build();}}
//在这个例子中,CarConfiguration 类使用 @Bean 注解来定义一个 Car 对象,它通过 CarBuilder 来一步步地设置 Car 对象的属性。最终,build() 方法被调用以创建完整的 Car 对象,并将其作为 Bean 注册到 Spring 容器中。通过这种方式,Spring 提供了一种灵活且可扩展的方式来配置和管理对象的创建,这正是建造者模式的核心思想。
原型模式(Prototype Pattern)

通过复制一个对象来创建另一个对象,也就是对象的克隆。比如,在一个游戏里,玩家可以通过复制来创建一个新的角色。

public interface Prototype {// 返回此对象的副本Prototype clone();
}// 具体的原型对象实现
public class ConcretePrototype implements Prototype {private String name;public ConcretePrototype(String name) {this.name = name;}@Overridepublic Prototype clone() {// 使用Java的Cloneable接口来实现深复制或浅复制try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {throw new IllegalStateException("Clone is not supported", e);}}// 其他与名称相关的操作方法public String getName() {return name;}
}// 客户端代码
public class PrototypeClient {public static void main(String[] args) {ConcretePrototype prototype = new ConcretePrototype("原始对象");ConcretePrototype clone = prototype.clone();clone.setName("修改后的对象");// 输出结果System.out.println("原始对象: " + prototype.getName());System.out.println("修改后的对象: " + clone.getName());}
}
适配器模式(Adapter Pattern)

将一个类的接口转换为另一个类所需的接口。比如,不同的充电器适配不同类型的手机。

// 老式收音机,只能播放AM信号
class OldRadio {public void playAM(String amStation) {// 播放AM信号}
}// 新式收音机,能够播放FM信号
class NewRadio {public void playFM(String fmStation) {// 播放FM信号}
}// FM适配器,适配老式收音机,使得其能够播放FM信号
class FmAdapter extends OldRadio {private NewRadio newRadio;public FmAdapter() {this.newRadio = new NewRadio();}@Overridepublic void playAM(String amStation) {// 老式收音机播放AM信号}public void playFM(String fmStation) {// 使用新式收音机播放FM信号this.newRadio.playFM(fmStation);}
}// 使用适配器
public class Main {public static void main(String[] args) {OldRadio oldRadio = new FmAdapter();oldRadio.playFM("FM101.7"); // 通过适配器调用新式收音机的播放方法}
}
//在这个例子中,FmAdapter类继承了OldRadio类,并提供了playFM方法。在playFM方法内部,它调用NewRadio类的playFM方法来播放FM信号。这样,通过FmAdapter,OldRadio就能够播放FM信号了。
桥接模式(Bridge Pattern)

将抽象与实现分离,使它们可以独立变化。比如,一个音乐播放器,音乐格式和播放器界面可以独立变化。

//有一个系统,需要处理不同类型的文件(例如PDF、Word文档等),每种类型的文件都需要进行不同的操作(例如打开、关闭、打印等)。我们可以使用桥接模式来设计这个系统。// 抽象化层
interface FileHandler {void openFile();void closeFile();void printFile();
}// 实现化层
class PdfFileHandler implements FileHandler {@Overridepublic void openFile() {// 打开PDF文件的逻辑}@Overridepublic void closeFile() {// 关闭PDF文件的逻辑}@Overridepublic void printFile() {// 打印PDF文件的逻辑}
}class WordFileHandler implements FileHandler {@Overridepublic void openFile() {// 打开Word文档的逻辑}@Overridepublic void closeFile() {// 关闭Word文档的逻辑}@Overridepublic void printFile() {// 打印Word文档的逻辑}
}// 桥接层
class FileManager {private FileHandler fileHandler;public void setFileHandler(FileHandler fileHandler) {this.fileHandler = fileHandler;}public void handleFile() {fileHandler.openFile();// 其他文件处理逻辑fileHandler.closeFile();}
}// 使用桥接模式
FileManager fileManager = new FileManager();
fileManager.setFileHandler(new PdfFileHandler());
fileManager.handleFile(); // 处理PDF文件fileManager.setFileHandler(new WordFileHandler());
fileManager.handleFile(); // 处理Word文档//在这个例子中,FileManager 类使用了桥接模式,它依赖于 FileHandler 接口,但并不关心具体实现。你可以随时更换 FileHandler 的实现,而不会影响 FileManager 的代码。桥接模式使得系统更加灵活,易于扩展。
装饰模式(Decorator Pattern)

在不改变原有对象的基础上,通过增加额外的功能来扩展对象。比如,在咖啡中加入不同的调料,如糖和奶油。

// 抽象组件(被装饰的对象)
interface Beverage {double cost();String getDescription();
}// 具体组件(被装饰的具体对象)
class Coffee extends Beverage {@Overridepublic double cost() {return 1.5;}@Overridepublic String getDescription() {return "Coffee";}
}// 抽象装饰类
interface Decorator extends Beverage {// 提供添加装饰的方法Beverage decorate(Beverage beverage);
}// 具体装饰类1(增加杯盖)
class CoffeeWithToppings extends Decorator {private Beverage beverage;public CoffeeWithToppings(Beverage beverage) {this.beverage = beverage;}@Overridepublic double cost() {return beverage.cost() + 0.5; // 假设杯盖增加的成本}@Overridepublic String getDescription() {return beverage.getDescription() + " with toppings";}@Overridepublic Beverage decorate(Beverage beverage) {return new CoffeeWithToppings(beverage);}
}// 客户端代码
public class DecoratorPatternDemo {public static void main(String[] args) {Beverage coffee = new Coffee();Beverage coffeeWithToppings = new CoffeeWithToppings(coffee);System.out.println("Cost of " + coffeeWithToppings.getDescription() + " is " + coffeeWithToppings.cost());}
}//在这个例子中,Beverage 是抽象组件,Coffee 是具体组件。Decorator 是抽象装饰类,CoffeeWithToppings 是具体装饰类,它继承了 Decorator 并实现了装饰方法 decorate(Beverage beverage)。客户端代码可以动态地创建带有不同装饰的饮料对象。
代理模式(Proxy Pattern)

为另一个对象提供一个替身或代表,以便控制对这个对象的访问。比如,在网络游戏中,玩家可以使用一个代理来控制角色。

// 抽象主题(Subject)接口
public interface Subject {void doSomething();
}// 真实主题(RealSubject)类
public class RealSubject implements Subject {@Overridepublic void doSomething() {System.out.println("RealSubject: Doing something real.");}
}// 代理主题(ProxySubject)类
public class ProxySubject implements Subject {private RealSubject realSubject;public ProxySubject() {// 懒加载,仅在需要时创建真实对象if (realSubject == null) {realSubject = new RealSubject();}}@Overridepublic void doSomething() {// 可以在这里添加额外的逻辑,比如记录日志或性能监控System.out.println("ProxySubject: Pre-processing...");realSubject.doSomething();System.out.println("ProxySubject: Post-processing...");}
}// 客户端代码
public class Client {public static void main(String[] args) {Subject subject = new ProxySubject();subject.doSomething(); // 通过代理对象调用真实对象的方法}
}
外观模式(Facade Pattern)

为子系统中的一组接口提供一个一致的界面。外观模式就像是汽车的方向盘。当你开车时,你不需要关心汽车引擎、变速器、离合器等内部部件是如何工作的。你只需要通过方向盘来控制汽车,如加速、减速、转向等。方向盘简化了你对汽车的操控,它隐藏了复杂的机械和电子系统,为你提供了一个简单的接口。

// 汽车类(复杂的子系统)
class Car {public void startEngine() {System.out.println("启动引擎");}public void accelerate() {System.out.println("加速");}public void brake() {System.out.println("刹车");}public void turnLeft() {System.out.println("向左转");}public void turnRight() {System.out.println("向右转");}
}// 外观类(提供简单的接口)
class CarFacade {private Car car;public CarFacade() {this.car = new Car();}// 简化的方法,背后调用Car类的方法public void drive() {car.startEngine();car.accelerate();car.turnLeft();car.turnRight();car.brake();}
}// 使用外观类
public class Main {public static void main(String[] args) {CarFacade carFacade = new CarFacade();carFacade.drive();}
}
//在这个例子中,CarFacade类是外观类,它隐藏了Car类的复杂性。当你调用CarFacade的drive()方法时,它会在幕后调用Car类中的各个方法来模拟一个驾驶过程。这样,你就不需要直接操作Car类的复杂方法,而是通过CarFacade来完成一系列的操作。在实际应用中,外观模式非常适合那些想要隐藏其内部复杂性并提供一个简单接口的系统。它可以帮助你简化客户端与子系统的交互,使得系统更易于使用和维护。
观察者模式(Observer Pattern)

当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。比如,在用户注册时发送邮件和短信通知。
Java 中观察者模式的实现通常涉及两个核心接口:Observable(被观察者)和 Observer(观察者)。

//创建一个被观察者类(Observable)
import java.util.List;
import java.util.Observable;
import java.util.Observer;public class Subject extends Observable {private String data;public void setData(String data) {this.data = data;setChanged(); // 标记状态已更改notifyObservers(data); // 通知所有观察者}
}//创建一个观察者类(Observer)
import java.util.Observable;
import java.util.Observer;public class Observer implements Observer {@Overridepublic void update(Observable o, Object arg) {// 当被观察者状态变化时,观察者会收到通知System.out.println("收到通知:" + arg);}
}//订阅和通知:观察者可以订阅被观察者,并在被观察者状态变化时收到通知
import java.util.List;
import java.util.Observable;
import java.util.Observer;public class Main {public static void main(String[] args) {Subject subject = new Subject();Observer observer = new Observer();subject.addObserver(observer);subject.setData("这是最新的数据"); // 设置数据并通知观察者}
}//在上面的例子中,Subject 类是一个被观察者,它维护了一个 Observable 对象,并重写了 setData 方法来设置数据并通知观察者。Observer 类是一个观察者,它实现了 Observer 接口,并在 update 方法中处理被观察者发送的通知。Main 类演示了如何创建一个被观察者和观察者,并让它们相互订阅和通知。
策略模式(Strategy Pattern)

定义一系列算法,并在运行时选择使用哪一个算法。比如,不同的信用卡支付方式。

// 行为接口
interface Strategy {void algorithm();
}// 行为1:快速算法
class FastAlgorithm implements Strategy {@Overridepublic void algorithm() {System.out.println("执行快速算法");}
}// 行为2:慢速算法
class SlowAlgorithm implements Strategy {@Overridepublic void algorithm() {System.out.println("执行慢速算法");}
}// 上下文类,它持有一个Strategy对象
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void execute() {strategy.algorithm();}
}// 使用策略模式
public class StrategyPatternDemo {public static void main(String[] args) {Strategy slowAlgorithm = new SlowAlgorithm();Strategy fastAlgorithm = new FastAlgorithm();Context context = new Context(slowAlgorithm);context.execute(); // 执行慢速算法context.setStrategy(fastAlgorithm);context.execute(); // 切换到快速算法}
}
//在这个例子中,Strategy 接口定义了一个算法,FastAlgorithm 和 SlowAlgorithm 类实现了不同的算法。Context 类包含一个 Strategy 对象,并通过 setStrategy 方法来切换不同的策略。StrategyPatternDemo 类展示了如何使用策略模式来切换算法。
模板方法模式(Template Method Pattern)

定义一个操作的骨架,将一些步骤延迟到子类中。比如,一个烹饪菜谱,步骤是固定的,但具体的配料和做法可以变化。

public abstract class AbstractTemplate {public final void templateMethod() {step1();step2();step3();}protected abstract void step1();protected abstract void step2();protected void step3() {// 这里的步骤3是固定的,不需要子类实现System.out.println("Step 3 performed.");}
}public class ConcreteTemplate extends AbstractTemplate {@Overrideprotected void step1() {System.out.println("ConcreteTemplate: Step 1 performed.");}@Overrideprotected void step2() {System.out.println("ConcreteTemplate: Step 2 performed.");}
}public class TemplateMethodTest {public static void main(String[] args) {AbstractTemplate abstractTemplate = new ConcreteTemplate();abstractTemplate.templateMethod();}
}//在这个例子中,AbstractTemplate 类定义了操作的模板 templateMethod(),并提供了 step3() 的具体实现。ConcreteTemplate 类继承自 AbstractTemplate,并重写了 step1() 和 step2() 方法,提供了具体的操作。TemplateMethodTest 类用于测试模板方法模式。当 TemplateMethodTest 类调用 abstractTemplate.templateMethod() 时,AbstractTemplate 类的 templateMethod() 方法会被执行,它首先调用 step1(),然后是 step2(),最后是 step3()。因为 step3() 已经在 AbstractTemplate 类中实现,所以它不会被 ConcreteTemplate 类重写。
迭代器模式(Iterator Pattern)

提供一种方法来顺序访问一个聚合对象中的各个元素。比如,一个用于遍历列表或数组的迭代器。

MyList<Integer> list = new MyList<>(new Integer[] {1, 2, 3, 4, 5});
Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer element = iterator.next();System.out.println(element);
}
组合模式(Composite Pattern)

将对象组合成树形结构,以表示“部分-整体”的层次结构。比如,一个公司的组织结构。

// 抽象组件(Component)
interface Component {void add(Component child);void remove(Component child);void print(); // 打印方法,用于演示
}// 叶节点(Leaf)
class Leaf implements Component {@Overridepublic void add(Component child) {// 叶节点没有子节点,所以这个方法不做任何事情}@Overridepublic void remove(Component child) {// 叶节点没有子节点,所以这个方法不做任何事情}@Overridepublic void print() {System.out.println("Leaf node"); // 叶节点的打印逻辑}
}// 组合对象(Composite)
class Composite implements Component {private List<Component> children = new ArrayList<>();@Overridepublic void add(Component child) {children.add(child);}@Overridepublic void remove(Component child) {children.remove(child);}@Overridepublic void print() {System.out.println("Composite node"); // 组合对象的打印逻辑for (Component child : children) {child.print();}}
}// 客户端代码
public class CompositePattern {public static void main(String[] args) {Component root = new Composite();root.add(new Leaf()); // 添加叶节点root.add(new Leaf()); // 添加另一个叶节点root.add(new Composite()); // 添加一个组合对象root.print(); // 打印整个组合}
}
//在这个例子中,Component是抽象组件,Leaf是叶节点,Composite是组合对象。Composite对象可以包含其他Component对象,而Leaf对象则没有子节点。print方法在组合模式中非常重要,它允许我们以一致的方式遍历整个组合并打印每个组件。在实际应用中,组合模式常用于GUI开发、文件系统和XML解析器等场景。
命令模式(Command Pattern)

将一个请求封装成一个对象,从而允许使用不同的请求、队列或日志来参数化其他对象。比如,一个远程控制的命令列表。

// 定义命令的接口
interface Command {void execute();void undo();
}// 具体命令的实现类
class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.doSomething(); // 调用接收者的操作}@Overridepublic void undo() {receiver.undoSomething(); // 调用接收者的撤销操作}
}// 接收者接口,定义了具体操作
interface Receiver {void doSomething();void undoSomething();
}// 具体接收者的实现类
class ConcreteReceiver implements Receiver {@Overridepublic void doSomething() {System.out.println("Doing something...");}@Overridepublic void undoSomething() {System.out.println("Undoing something...");}
}// 客户端类,创建命令并执行
class Client {public static void main(String[] args) {Receiver receiver = new ConcreteReceiver();Command command = new ConcreteCommand(receiver);command.execute(); // 执行命令command.undo(); // 撤销命令}
}//在这个例子中,Command 接口定义了 execute() 和 undo() 方法,表示执行命令和撤销命令。ConcreteCommand 类实现了 Command 接口,并持有 Receiver 对象,这样它就可以调用 Receiver 的操作。ConcreteReceiver 类实现了 Receiver 接口,定义了实际的执行和撤销操作。Client 类创建了一个 Command 对象并调用其 execute() 和 undo() 方法。
备忘录模式(Memento Pattern)

在不泄露内部状态的情况下,捕获一个对象的内部状态,并在之后恢复到该状态。比如,游戏中的存档和读档功能。

public class GameState {private int score;private int level;// 创建备忘录public Memento createMemento() {return new Memento(this.score, this.level);}// 恢复备忘录public void restoreMemento(Memento memento) {this.score = memento.getScore();this.level = memento.getLevel();}
}public class Memento {private int score;private int level;public Memento(int score, int level) {this.score = score;this.level = level;}public int getScore() {return score;}public int getLevel() {return level;}
}public class GamePlayer {private GameState gameState;// 保存游戏状态public void saveGameState() {Memento memento = gameState.createMemento();// 这里可以将备忘录存储在文件、数据库或其他持久化介质中}// 恢复游戏状态public void restoreGameState() {Memento memento = // 从文件、数据库等加载备忘录gameState.restoreMemento(memento);}
}
状态模式(State Pattern)

允许对象在内部状态改变时改变它的行为。比如,一个自动售货机根据投入的硬币数量和选择的商品来改变状态。

// 状态接口
interface State {void insertCoin();void selectItem();void dispenseItem();void refundCoin();
}// 状态类(具体状态1:有足够的硬币)
class State1 implements State {@Overridepublic void insertCoin() {// 如果有足够的硬币,增加硬币数量System.out.println("状态1: 插入硬币,硬币数量增加");}@Overridepublic void selectItem() {// 如果有足够的硬币,允许选择商品System.out.println("状态1: 选择商品");}@Overridepublic void dispenseItem() {// 如果有足够的硬币,发放商品System.out.println("状态1: 发放商品");}@Overridepublic void refundCoin() {// 如果有足够的硬币,退回硬币System.out.println("状态1: 退回硬币");}
}// 状态类(具体状态2:硬币不足)
class State2 implements State {@Overridepublic void insertCoin() {// 硬币不足,提示投入更多的硬币System.out.println("状态2: 硬币不足,请投入更多硬币");}@Overridepublic void selectItem() {// 硬币不足,不允许选择商品System.out.println("状态2: 硬币不足,不允许选择商品");}@Overridepublic void dispenseItem() {// 硬币不足,不允许发放商品System.out.println("状态2: 硬币不足,不允许发放商品");}@Overridepublic void refundCoin() {// 硬币不足,不允许退回硬币System.out.println("状态2: 硬币不足,不允许退回硬币");}
}// 上下文类
class Context {private State state;public Context(State state) {this.state = state;}public void insertCoin() {state.insertCoin();}public void selectItem() {state.selectItem();}public void dispenseItem() {state.dispenseItem();}public void refundCoin() {state.refundCoin();}// 可以根据需要添加改变状态的方法public void changeState(State newState) {state = newState;}
}public class StatePatternDemo {public static void main(String[] args) {Context context = new Context(new State1());context.insertCoin(); // 插入硬币,状态1context.selectItem(); // 选择商品,状态1context.dispenseItem(); // 发放商品,状态1context.refundCoin(); // 退回硬币,状态1// 假设硬币不足,改变状态context.changeState(new State2());context.insertCoin(); // 硬币不足,状态2context.selectItem(); // 硬币不足,状态2context.dispenseItem(); // 硬币不足,状态2context.refundCoin(); // 硬币不足,状态2}
}
//在这个例子中,State 接口定义了售货机可能执行的操作。State1 和 State2 是两个具体状态类,它们分别表示售货机有足够的硬币和硬币不足时的行为。Context 类负责维护当前状态,并提供操作方法。在 main 方法中,我们创建了一个 Context 对象,并设置了初始状态。然后,我们通过调用 insertCoin, selectItem, dispenseItem 和 refundCoin 方法来改变售货机的状态并观察其行为。最后,我们模拟硬币不足的情况,通过 changeState 方法改变状态,并观察新的行为。
职责链模式(Chain of Responsibility Pattern)

将请求的发送者和接收者解耦,使得可以在链中传递请求,直到有一个对象处理它。比如,在一个公司中,问题的上报和解决流程。

import java.util.LinkedList;
import java.util.List;// 抽象Handler类
abstract class Handler {Handler successor; // 指向下一个Handlerpublic void setSuccessor(Handler successor) {this.successor = successor;}public abstract void handleRequest();
}// 具体Handler子类1: Level1Handler
class Level1Handler extends Handler {public void handleRequest() {// 如果Level1Handler可以处理请求,处理它if (canHandleRequest()) {System.out.println("Level1Handler handling request...");} else {// 如果不能处理,传递给下一个Handlerif (successor != null) {successor.handleRequest();} else {System.out.println("No more handlers, request ignored.");}}}// 假设这个方法用于检查是否可以处理请求private boolean canHandleRequest() {// 这里可以添加具体的条件判断return true; // 或者根据需要返回其他结果}
}// 具体Handler子类2: Level2Handler
class Level2Handler extends Handler {public void handleRequest() {// 同上if (canHandleRequest()) {System.out.println("Level2Handler handling request...");} else {if (successor != null) {successor.handleRequest();} else {System.out.println("No more handlers, request ignored.");}}}private boolean canHandleRequest() {// 这里可以添加具体的条件判断return true; // 或者根据需要返回其他结果}
}// 创建一个Handler链
public class ChainExample {public static void main(String[] args) {Handler level1 = new Level1Handler();Handler level2 = new Level2Handler();// 将level1设置为level2的successorlevel1.setSuccessor(level2);// 开始处理请求level1.handleRequest();}
}
//在这个例子中,Level1Handler 和 Level2Handler 是具体的Handler子类,它们各自负责特定的请求处理。在main方法中,我们创建了两个Handler对象,并将第一个Handler(Level1Handler)设置为第二个Handler(Level2Handler)的successor。然后,我们调用Level1Handler的handleRequest方法来开始处理请求。如果Level1Handler可以处理请求,它就会处理;如果不能,它会传递给Level2Handler。如果Level2Handler也不能处理,那么请求将会被忽略,因为successor为null,表明这是Handler链的末端。在实际应用中,职责链模式可以用于日志记录、异常处理、事件分发器和访问控制等领域。
中介者模式(Mediator Pattern)

减少对象之间的直接通信。中介者对象封装了一系列对象交互,使得对象不需要彼此直接引用。比如,在团队合作中,使用项目管理工具来协调不同成员的工作。

//抽象中介者接口,它定义了各个参与者之间可以进行的操作
public interface Mediator {void register(Colleague colleague);void sendMessage(Colleague sender, Colleague receiver, String message);
}//中介者类,它维护一个参与者(同事)列表,并负责转发消息
public class ConcreteMediator implements Mediator {private List<Colleague> colleagues = new ArrayList<>();@Overridepublic void register(Colleague colleague) {colleagues.add(colleague);}@Overridepublic void sendMessage(Colleague sender, Colleague receiver, String message) {// 转发消息给接收者receiver.receiveMessage(sender, message);}
}//参与者的抽象类,它定义了接受消息的方法
public abstract class Colleague {private Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}public void sendMessage(Colleague receiver, String message) {mediator.sendMessage(this, receiver, message);}public abstract void receiveMessage(Colleague sender, String message);
}//实现具体的参与者类,它们通过中介者进行通信
public class ConcreteColleagueA extends Colleague {public ConcreteColleagueA(Mediator mediator) {super(mediator);}@Overridepublic void receiveMessage(Colleague sender, String message) {// 处理收到的消息System.out.println("ColleagueA received message: " + message + " from " + sender.getClass().getSimpleName());}
}public class ConcreteColleagueB extends Colleague {public ConcreteColleagueB(Mediator mediator) {super(mediator);}@Overridepublic void receiveMessage(Colleague sender, String message) {// 处理收到的消息System.out.println("ColleagueB received message: " + message + " from " + sender.getClass().getSimpleName());}
}//使用中介者模式
public class Main {public static void main(String[] args) {Mediator mediator = new ConcreteMediator();Colleague colleagueA = new ConcreteColleagueA(mediator);Colleague colleagueB = new ConcreteColleagueB(mediator);// 注册参与者mediator.register(colleagueA);mediator.register(colleagueB);// 发送消息colleagueA.sendMessage(colleagueB, "Hello from ColleagueA");colleagueB.sendMessage(colleagueA, "Hello from ColleagueB");}
}//在这个例子中,ConcreteMediator 类是中介者,它管理着 ConcreteColleagueA 和 ConcreteColleagueB 的通信。每个参与者只需要通过中介者发送消息,而不需要知道其他参与者的具体细节。这种设计使得系统的结构更加清晰,且更容易维护和扩展。
访问者模式(Visitor Pattern)

表示一个作用于某对象结构中的各个元素的操作。比如,对不同类型的文件进行统计和分析。

// 抽象元素
abstract class Element {public abstract void accept(Visitor visitor);
}// 具体元素1
class ConcreteElement1 extends Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 具体元素2
class ConcreteElement2 extends Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 访问者
interface Visitor {void visit(Element element);
}// 具体访问者
class ConcreteVisitor implements Visitor {@Overridepublic void visit(Element element) {if (element instanceof ConcreteElement1) {((ConcreteElement1) element).operate1();} else if (element instanceof ConcreteElement2) {((ConcreteElement2) element).operate2();} else {throw new IllegalArgumentException("Unknown element type: " + element.getClass().getName());}}
}// 使用访问者
Element element1 = new ConcreteElement1();
Element element2 = new ConcreteElement2();Visitor visitor = new ConcreteVisitor();
element1.accept(visitor);
element2.accept(visitor);//在这个例子中,Element 是抽象元素,ConcreteElement1 和 ConcreteElement2 是具体元素,Visitor 是访问者接口,ConcreteVisitor 是具体访问者。accept 方法和 visit 方法是访问者模式的核心,它们允许访问者对元素执行特定的操作。
解释器模式(Interpreter Pattern)

提供解释一种语言的语法表示的机制。比如,一个简单的计算器,可以解释和执行简单的数学表达式。这种模式通常用于构建简单的语言解析器,例如配置文件解析、简单的脚本语言解释器或者命令行工具等。

// 操作接口
interface IOperation {int interpret(int a, int b);
}// 操作类(+, -, *, /)
class PlusOperation implements IOperation {@Overridepublic int interpret(int a, int b) {return a + b;}
}class MinusOperation implements IOperation {@Overridepublic int interpret(int a, int b) {return a - b;}
}// 解释器类
class ArithmeticExpressionInterpreter {private IOperation operation;public ArithmeticExpressionInterpreter(IOperation operation) {this.operation = operation;}public int interpret(String expression) {// 解析表达式并执行String[] parts = expression.split(" ");int a = Integer.parseInt(parts[0]);int b = Integer.parseInt(parts[1]);return operation.interpret(a, b);}
}public class Main {public static void main(String[] args) {IOperation plusOperation = new PlusOperation();IOperation minusOperation = new MinusOperation();ArithmeticExpressionInterpreter interpreter = new ArithmeticExpressionInterpreter(plusOperation);int result = interpreter.interpret("10 20"); // 输出: 30System.out.println(result);interpreter = new ArithmeticExpressionInterpreter(minusOperation);result = interpreter.interpret("10 20"); // 输出: -10System.out.println(result);}
}//在这个例子中,IOperation 接口定义了操作的协议,而 PlusOperation 和 MinusOperation 类实现了这些操作。ArithmeticExpressionInterpreter 类则负责解释表达式并执行相应的操作。Main 类展示了如何创建解释器并使用它来解释简单的算术表达式。
职责模式(Job Pattern)

将一个大任务分解成小任务,每个小任务都可以独立执行。比如,项目管理中的任务分解。
这些模式并不是孤立使用的,它们可以结合在一起解决更复杂的设计问题。了解这些模式可以帮助开发者更好地理解软件设计中的问题和解决方案。

public abstract class RequestHandler {public abstract void handleRequest(Request request);
}public class ConcreteRequestHandler1 extends RequestHandler {@Overridepublic void handleRequest(Request request) {// 检查请求是否属于自己的职责if (request.getType() == RequestType.TYPE1) {// 处理请求handleType1Request(request);} else {// 转发请求给其他处理器ConcreteRequestHandler2 otherHandler = new ConcreteRequestHandler2();otherHandler.handleRequest(request);}}private void handleType1Request(Request request) {// 处理类型1的请求}
}public class ConcreteRequestHandler2 extends RequestHandler {@Overridepublic void handleRequest(Request request) {// 检查请求是否属于自己的职责if (request.getType() == RequestType.TYPE2) {// 处理请求handleType2Request(request);} else {// 转发请求给其他处理器ConcreteRequestHandler1 otherHandler = new ConcreteRequestHandler1();otherHandler.handleRequest(request);}}private void handleType2Request(Request request) {// 处理类型2的请求}
}public class Client {public static void main(String[] args) {RequestHandler handler1 = new ConcreteRequestHandler1();RequestHandler handler2 = new ConcreteRequestHandler2();// 发送请求给处理程序,处理程序会根据请求类型进行相应处理handler1.handleRequest(new Request(RequestType.TYPE1));handler2.handleRequest(new Request(RequestType.TYPE2));}
}//在这个例子中,RequestHandler 是抽象类,定义了处理请求的抽象方法。ConcreteRequestHandler1 和 ConcreteRequestHandler2 是具体处理类,它们分别负责处理不同类型的请求。当 Client 发送请求时,RequestHandler 会根据请求的类型选择相应的处理类来处理请求。如果请求不属于自己的职责,就会转发给其他处理类。这种方式可以确保每个请求都有对应的处理程序,同时处理程序之间是松耦合的,便于维护和扩展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663978.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python与Go中详细的异常处理机制|面试题

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c;主要职责&#xff1a;测试开发、CI/CD 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。 &#x1f60a; 座右铭&#xff1a;不…

django+flask+python高校教材管理系统47nia

本.4论文结构 绪论&#xff1a;剖析项目可行性&#xff0c;表明研究方向。 开发技术&#xff1a;系统关键运用了Python技术性、Django框架、B/S架构和myspl数据库查询&#xff0c;并进行了详细介绍[6]。 系统分析&#xff1a;包含系统的总体构造&#xff0c;用例图和结构图。 系…

故障诊断 | 一文解决,CNN-LSTM卷积神经网络-长短期记忆神经网络组合模型的故障诊断(Matlab)

效果一览 文章概述 故障诊断 | 一文解决,CNN-LSTM卷积神经网络-长短期记忆神经网络组合模型的故障诊断(Matlab) 模型描述 CNN-LSTM模型是一种结合了卷积神经网络(Convolutional Neural Network)和长短期记忆神经网络(Long Short-Term Memory)的组合模型,常用于数据故障…

SpringBoot使用Kafka详解含完整代码

1. 前言 随着大数据和实时处理需求的增长&#xff0c;Kafka作为一种分布式流处理平台&#xff0c;与Spring Boot的集成变得尤为重要。本文将详细探讨如何在Spring Boot应用程序中设置和使用Kafka&#xff0c;从基础概念到高级特性&#xff0c;通过实际代码示例帮助读者深入理解…

大语言模型的未来进化路径及其影响

随着人工智能技术的飞速发展&#xff0c;大语言模型已成为智能时代的重要标志之一。从早期基于规则和统计学习的语言模型&#xff0c;到如今基于深度学习框架下的Transformer架构&#xff0c;如GPT系列、BERT等&#xff0c;大语言模型已经在自然语言处理领域取得了前所未有的突…

uniapp中封装一个svg转base64的组件

uniapp中由于不支持svg--》base64&#xff0c;同时无法使用h5中atob&#xff0c;这里我们采用js-base64插件实现这样一个组件&#xff0c;只要传人svg的代码即可在uniapp中转为base64&#xff0c;同时支持自定义参数&#xff0c;比如宽度&#xff0c;高度,等 1 安装 npm inst…

《动手学深度学习(PyTorch版)》笔记6.3

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

Python实现PDF到HTML的转换

PDF文件是共享和分发文档的常用选择&#xff0c;但提取和再利用PDF文件中的内容可能会非常麻烦。而利用Python将PDF文件转换为HTML是解决此问题的理想方案之一&#xff0c;这样做可以增强文档可访问性&#xff0c;使文档可搜索&#xff0c;同时增强文档在不同场景中的实用性。此…

【FPGA原型验证】附录基础知识:FPGA/CPLD基本结构与实现原理

聚焦Xilinx ISE 介绍Xilinx公司及其产品的基本情况,并在此基础上描述了CPLD和FPGA的内部结构及基本原理。 1.1 Xilinx公司及其产品介绍 总部设在加利福尼亚圣何塞市(San Jose)的Xilinx是全球领先的可编程逻辑解决方案的供应商,图1-1为公司标志。 Xilinx公司的业务是研发…

后端——go系统学习笔记(不断更新中......)

数组 固定大小 初始化 arr1 : [3]int{1, 2, 3} arr2 : [...]int{1, 2, 3} var arr3 []int var arr4 [4]int切片 长度是动态的 初始化 arr[0:3] slice : []int{1,2,3} slice : make([]int, 10)len和cap len是获取切片、数组、字符串的长度——元素的个数cap是获取切片的容量—…

Android PMS——ADB命令安装流程(七)

前面的文章我们介绍了系统应用解析流程和通过 PackageInstaller.apk安装应用程序的相关流程,这一篇我们来分析使用 ADB 命令来实现 APK 安装流程。 一、ADB安装命令 ADB命令使用 adb install [选项] [APK绝对路径] 常见选项如下: -r:覆盖安装,保存原有数据; -t:…

深度学习入门笔记(七)卷积神经网络CNN

我们先来总结一下人类识别物体的方法: 定位。这一步对于人眼来说是一个很自然的过程,因为当你去识别图标的时候,你就已经把你的目光放在了图标上。虽然这个行为不是很难,但是很重要。看线条。有没有文字,形状是方的圆的,还是长的短的等等。看细节。纹理、颜色、方向等。卷…

Java正则表达式之Pattern和Matcher

目录 前言一、Pattern和Matcher的简单使用二、Pattern详解2.1 Pattern 常用方法2.1.1 compile(String regex)2.1.2 matches(String regex, CharSequence input)2.1.3 split(CharSequence input)2.1.4 pattern()2.1.5 matcher(CharSequence input) 三、Matcher详解3.1 Matcher 常…

JSP和JSTL板块:第三节 JSP四大域对象 来自【汤米尼克的JAVAEE全套教程专栏】

JSP和JSTL板块&#xff1a;第三节 JSP四大域对象 一、page范围二、request范围三、session范围四、application范围 在服务器和客户端之间、各个网页之间、哪怕同一个网页之内&#xff0c;总是需要传递各种参数值&#xff0c;这时JSP的内置对象就是传递这些参数的载具。内置对象…

Redis面试题38

人工智能在医疗领域有哪些应用&#xff1f; 答&#xff1a;人工智能在医疗领域有许多应用&#xff0c;下面是一些常见的例子&#xff1a; 图像识别和辅助诊断&#xff1a;人工智能可以用于图像识别和辅助诊断&#xff0c;例如在医学影像领域&#xff0c;人工智能可以辅助医生分…

​(四)hive的搭建2

在&#xff08;三&#xff09;hive的搭建1中我们搭建好了hive环境&#xff0c;但是只能本地访问&#xff0c;在本节中配置Hive的访问方式。 1.元数据服务的方式 1.1 编辑hive-site.xml sudo vi hive-site.xml 在文件最后增加以下内容 <!– 指定存储元数据要连接的地址 –…

WebGL 1.0 内置函数

前言 本篇文章介绍WebGL 1.0 shader中支持的内置函数 角度弧度转化 角度转弧度radians 计算公式&#xff1a; R π d e g r e e 180 R \pi \times degree \div 180 Rπdegree180 float radians(float degree) vec2 radians(vec2 degree) vec3 radians(vec3 degree)…

无里程计下的纯跟踪算法实现

文章目录 概要生成相机坐标系下的三维坐标无里程计下的纯跟踪算法实现 概要 当你只有一个相机的时候&#xff0c;想要快速实现机器人跟随功能&#xff0c;没有里程计的情况下&#xff0c;就可以看这里了。这篇博文实现了一个无里程计下的纯跟踪算法。 生成相机坐标系下的三维…

1、安全开发-Python爬虫EDUSRC目标FOFA资产Web爬虫解析库

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正 前言&#xff1a; 主要包含对requests库和Web爬虫解析库的使用&#xff0c;python爬虫自动化&#xff0c;批量信息收集 Python开发工具&#xff1a;PyCharm 2022.1 激活破解码_安装教程 (2022年8月25日…

For debugging consider passing CUDA_LAUNCH_BLOCKING=1.

环境&#xff1a; wsl ubuntu22.04 vits2 问题描述&#xff1a; RuntimeError: CUDA error: unknown error [rank0]: CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect. [rank0]: For debugging …