当前位置: 首页 > news >正文

设计模式的原理及深入解析

创建型模式

创建型模式主要关注对象的创建过程,旨在通过不同的方式创建对象,以满足不同的需求。

工厂方法模式

定义:定义一个创建对象的接口,让子类决定实例化哪一个类。

解释:工厂方法模式通过定义一个创建对象的接口,允许子类决定实例化哪一个类。这样,客户端代码可以针对接口编程,而不必依赖于具体类。

代码示例

// 产品接口
interface Product {void use();
}// 具体产品A
class ConcreteProductA implements Product {public void use() {System.out.println("Using ConcreteProductA");}
}// 具体产品B
class ConcreteProductB implements Product {public void use() {System.out.println("Using ConcreteProductB");}
}// 抽象工厂
abstract class Creator {public abstract Product factoryMethod();public void someOperation() {Product product = factoryMethod();product.use();}
}// 具体工厂A
class ConcreteCreatorA extends Creator {public Product factoryMethod() {return new ConcreteProductA();}
}// 具体工厂B
class ConcreteCreatorB extends Creator {public Product factoryMethod() {return new ConcreteProductB();}
}

抽象工厂模式

定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

解释:抽象工厂模式通过定义一个创建对象的接口,允许子类决定实例化哪一个类。这样,客户端代码可以针对接口编程,而不必依赖于具体类。

代码示例

// 产品A接口
interface ProductA {void use();
}// 产品B接口
interface ProductB {void use();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {public void use() {System.out.println("Using ConcreteProductA1");}
}// 具体产品B1
class ConcreteProductB1 implements ProductB {public void use() {System.out.println("Using ConcreteProductB1");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {public void use() {System.out.println("Using ConcreteProductA2");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {public void use() {System.out.println("Using ConcreteProductB2");}
}// 抽象工厂
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA1();}public ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {public ProductA createProductA() {return new ConcreteProductA2();}public ProductB createProductB() {return new ConcreteProductB2();}
}

建造者模式

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

解释:建造者模式通过将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这样,客户端代码可以针对接口编程,而不必依赖于具体类。

代码示例

// 产品类
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 Parts: " + partA + " " + partB + " " + partC);}
}// 抽象建造者
interface Builder {void buildPartA();void buildPartB();void buildPartC();Product getProduct();
}// 具体建造者
class ConcreteBuilder implements Builder {private Product product = new Product();public void buildPartA() {product.setPartA("PartA");}public void buildPartB() {product.setPartB("PartB");}public void buildPartC() {product.setPartC("PartC");}public Product getProduct() {return product;}
}// 指挥者
class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPartA();builder.buildPartB();builder.buildPartC();}
}

原型模式

定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

解释:原型模式通过复制现有实例来创建新实例,而不是通过新建实例。这样,可以避免复杂的构造过程。

代码示例

// 原型类
class Prototype implements Cloneable {private String prototypeName;public Prototype(String prototypeName) {this.prototypeName = prototypeName;}public String getPrototypeName() {return prototypeName;}public void setPrototypeName(String prototypeName) {this.prototypeName = prototypeName;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}// 客户端代码
public class Client {public static void main(String[] args) throws CloneNotSupportedException {Prototype p1 = new Prototype("Prototype1");Prototype p2 = (Prototype) p1.clone();p2.setPrototypeName("Prototype2");System.out.println(p1.getPrototypeName());System.out.println(p2.getPrototypeName());}
}
单例模式

定义:确保一个类只有一个实例,并提供一个全局访问点。

解释:单例模式通过确保一个类只有一个实例,并提供一个全局访问点,来控制对象的创建和访问。这样,可以避免创建多个实例,节省资源。

// 单例类
class Singleton {private static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}// 客户端代码
public class Client {public static void main(String[] args) {Singleton s1 = Singleton.getInstance();Singleton s2 = Singleton.getInstance();System.out.println(s1 == s2); // 输出:true}
}

结构型模式

结构型模式主要关注对象之间的组合,通过组合对象来实现新的功能,而不改变对象的结构。

适配器模式

定义:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

解释:适配器模式通过将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

// 目标接口
interface Target {void request();
}// 需要适配的类
class Adaptee {public void specificRequest() {System.out.println("Specific request");}
}// 适配器
class Adapter extends Adaptee implements Target {public void request() {specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Target target = new Adapter();target.request();}
}

装饰器模式

定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

解释:装饰器模式通过动态地给一个对象添加一些额外的职责,使得增加功能更加灵活。

// 抽象构件
interface Component {void operation();
}// 具体构件
class ConcreteComponent implements Component {public void operation() {System.out.println("ConcreteComponent");}
}// 装饰抽象类
abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}public void operation() {component.operation();}
}// 具体装饰类A
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}public void operation() {super.operation();addBehavior();}public void addBehavior() {System.out.println("ConcreteDecoratorA");}
}// 具体装饰类B
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}public void operation() {super.operation();addBehavior();}public void addBehavior() {System.out.println("ConcreteDecoratorB");}
}// 客户端代码
public class Client {public static void main(String[] args) {Component component = new ConcreteComponent();component = new ConcreteDecoratorA(component);component = new ConcreteDecoratorB(component);component.operation();}
}

桥接模式

定义:将抽象部分与实现部分分离,使它们都可以独立地变化。

解释:桥接模式通过将抽象部分与实现部分分离,使它们都可以独立地变化。

// 抽象类
abstract class Abstraction {protected Implementor implementor;public Abstraction(Implementor implementor) {this.implementor = implementor;}abstract public void operation();
}// 实现接口
interface Implementor {void implement();
}// 具体实现A
class ConcreteImplementorA implements Implementor {public void implement() {System.out.println("ConcreteImplementorA");}
}// 具体实现B
class ConcreteImplementorB implements Implementor {public void implement() {System.out.println("ConcreteImplementorB");}
}// 具体抽象类RefinedAbstraction
class RefinedAbstraction extends Abstraction {public RefinedAbstraction(Implementor implementor) {super(implementor);}public void operation() {implementor.implement();}
}// 客户端代码
public class Client {public static void main(String[] args) {Implementor implementor = new ConcreteImplementorA();Abstraction abstraction = new RefinedAbstraction(implementor);abstraction.operation();}
}

组合模式

定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得客户对单个对象和组合对象的使用具有一致性。

解释:组合模式通过将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户对单个对象和组合对象的使用具有一致性。

// 抽象构件
abstract class Component {protected String name;public Component(String name) {this.name = name;}abstract public void add(Component component);abstract public void remove(Component component);abstract public void display(int depth);
}// 叶子构件
class Leaf extends Component {public Leaf(String name) {super(name);}public void add(Component component) {}public void remove(Component component) {}public void display(int depth) {System.out.println("-".repeat(depth) + name);}
}// 树枝构件
class Composite extends Component {private List<Component> childList = new ArrayList<>();public Composite(String name) {super(name);}public void add(Component component) {childList.add(component);}public void remove(Component component) {childList.remove(component);}public void display(int depth) {System.out.println("-".repeat(depth) + name);for (Component component : childList) {component.display(depth + 2);}}
}// 客户端代码
public class Client {public static void main(String[] args) {Component root = new Composite("root");Component branch1 = new Composite("branch1");Component branch2 = new Composite("branch2");Component leaf1 = new Leaf("leaf1");Component leaf2 = new Leaf("leaf2");root.add(branch1);root.add(branch2);branch1.add(leaf1);branch2.add(leaf2);root.display(1);}
}

外观模式

定义:为子系统中的一组接口提供一个一致的界面。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

解释:外观模式通过为子系统中的一组接口提供一个一致的界面,使得这一子系统更加容易使用。
实现特点

  • 封装子系统复杂交互逻辑
  • 对外提供简化访问入口
  • 降低客户端与子系统的耦合度
// 子系统组件A
class ClassA {public void operationA() {System.out.println("执行A类操作");}
}// 子系统组件B
class ClassB {public void operationB() {System.out.println("执行B类操作");}
}// 统一外观接口
class Facade {private ClassA componentA = new ClassA();private ClassB componentB = new ClassB();public void unifiedOperation() {componentA.operationA();componentB.operationB();}
}// 使用示例
public class Client {public static void main(String[] args) {Facade gateway = new Facade();gateway.unifiedOperation();}
}


享元模式

定义:运用共享技术有效地支持大量细粒度的对象。

解释:享元模式通过运用共享技术有效地支持大量细粒度的对象。
核心机制

  • 分离内部状态(固有属性)与外部状态(可变属性)
  • 使用工厂管理共享对象池
  • 适用于存在大量重复对象的场景
// 抽象享元接口
interface Shape {void draw(int positionX, int positionY);
}// 具体享元对象
class Circle implements Shape {private String color;public Circle(String color) {this.color = color;}@Overridepublic void draw(int x, int y) {System.out.println("绘制" + color + "色圆形于(" + x + "," + y + ")");}
}// 对象工厂
class ShapeFactory {private Map<String, Shape> shapePool = new HashMap<>();public Shape getShape(String color) {if (!shapePool.containsKey(color)) {shapePool.put(color, new Circle(color));}return shapePool.get(color);}
}// 使用示例
public class Client {public static void main(String[] args) {ShapeFactory factory = new ShapeFactory();String[] colors = {"红", "蓝", "绿"};for(int i=0; i<10; i++){Shape shape = factory.getShape(colors[i%3]);shape.draw(i*10, i*5);}}
}


代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问。

解释:代理模式通过为其他对象提供一种代理以控制对这个对象的访问。
典型应用

  • 远程访问代理
  • 权限控制代理
  • 延迟加载代理
// 服务接口
interface Database {void query(String sql);
}// 实际服务对象
class DatabaseServer implements Database {public void query(String sql) {System.out.println("执行查询:" + sql);}
}// 代理控制器
class ProxyServer implements Database {private DatabaseServer server;private String accessLevel;public ProxyServer(String accessLevel) {this.accessLevel = accessLevel;}private boolean checkAccess() {return "admin".equals(accessLevel);}@Overridepublic void query(String sql) {if(!checkAccess()){System.out.println("权限拒绝");return;}if(server == null){server = new DatabaseServer(); // 延迟加载}server.query(sql);}
}// 使用示例
public class Client {public static void main(String[] args) {Database proxy = new ProxyServer("user");proxy.query("SELECT * FROM users");Database adminProxy = new ProxyServer("admin");adminProxy.query("DELETE FROM logs");}
}


行为型模式

行为型模式主要关注对象之间的通信,通过定义对象之间的通信方式,来实现特定的行为。

解释器模式

定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

解释:解释器模式通过给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
组成要素

  • 抽象表达式接口
  • 终结符表达式(基本元素)
  • 非终结符表达式(组合规则)
// 表达式接口
interface Expression {boolean evaluate(String context);
}// 基础表达式
class KeywordExpression implements Expression {private String keyword;public KeywordExpression(String word) {this.keyword = word;}@Overridepublic boolean evaluate(String text) {return text.contains(keyword);}
}// 组合表达式
class OrExpression implements Expression {private Expression left;private Expression right;public OrExpression(Expression left, Expression right) {this.left = left;this.right = right;}@Overridepublic boolean evaluate(String text) {return left.evaluate(text) || right.evaluate(text);}
}// 使用示例
public class Client {public static void main(String[] args) {Expression expr1 = new KeywordExpression("紧急");Expression expr2 = new KeywordExpression("重要");Expression complexExpr = new OrExpression(expr1, expr2);System.out.println(complexExpr.evaluate("本周会议内容"));  // falseSystem.out.println(complexExpr.evaluate("紧急通知!"));    // true}
}


模板方法模式

定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。

解释:模板方法模式通过在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
设计要点

  1. 使用final修饰模板方法防止重写
  2. 抽象方法定义可变步骤
  3. 钩子方法实现流程控制
// 抽象类
abstract class AbstractClass {public final void templateMethod() {primitiveOperation1();primitiveOperation2();}protected abstract void primitiveOperation1();protected abstract void primitiveOperation2();
}// 具体子类A
class ConcreteClassA extends AbstractClass {protected void primitiveOperation1() {System.out.println("ConcreteClassA primitiveOperation1");}protected void primitiveOperation2() {System.out.println("ConcreteClassA primitiveOperation2");}
}// 具体子类B
class ConcreteClassB extends AbstractClass {protected void primitiveOperation1() {System.out.println("ConcreteClassB primitiveOperation1");}protected void primitiveOperation2() {System.out.println("ConcreteClassB primitiveOperation2");}
}// 客户端代码
public class Client {public static void main(String[] args) {AbstractClass abstractClass = new ConcreteClassA();abstractClass.templateMethod();abstractClass = new ConcreteClassB();abstractClass.templateMethod();}
}

以下是对四个设计模式的整理说明,采用标准技术文档格式呈现:

职责链模式

定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

解释:职责链模式通过使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

实现原理

  1. 抽象处理者定义处理接口和后续链接
  2. 具体处理者实现具体处理逻辑:
    • 能处理时直接处理
    • 不能处理时转给后继对象
  3. 客户端构建处理链
abstract class Handler {protected Handler next;public void setNext(Handler next) {this.next = next;}public abstract void process(int value);
}class RangeHandler extends Handler {private final int min;private final int max;public RangeHandler(int min, int max) {this.min = min;this.max = max;}@Overridepublic void process(int value) {if (value >= min && value <= max) {System.out.println("Processed by "+getClass().getSimpleName());} else if (next != null) {next.process(value);}}
}// 使用示例
Handler chain = new RangeHandler(0,10);
chain.setNext(new RangeHandler(11,20));
chain.setNext(new RangeHandler(21,30));
chain.process(25);

命令模式

定义:将一个请求封装为一个对象,从而使你可以用不同的请求、队列或者请求日志来参数化其他对象。命令模式也支持可撤销的操作。

解释:命令模式通过将一个请求封装为一个对象,从而使你可以用不同的请求、队列或者请求日志来参数化其他对象。命令模式也支持可撤销的操作。

核心组件

  • 命令接口:声明执行方法
  • 具体命令:绑定接收者与操作
  • 调用者:触发命令执行
  • 接收者:实际业务逻辑执行者
interface Command {void execute();void undo();
}class LightCommand implements Command {private final Light light;private boolean prevState;public LightCommand(Light light) {this.light = light;}@Overridepublic void execute() {prevState = light.isOn();light.toggle();}@Overridepublic void undo() {light.setState(prevState);}
}// 使用示例
RemoteControl remote = new RemoteControl();
remote.setCommand(new LightCommand(light));
remote.pressButton();

状态模式

定义:允许对象在内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

解释:状态模式通过允许对象在内部状态改变时改变它的行为,使得对象看起来似乎修改了它的类。

实现要点

  1. 定义状态接口
  2. 实现具体状态类
  3. 上下文对象维护当前状态
interface State {void handle(Context context);
}class ActiveState implements State {@Overridepublic void handle(Context context) {System.out.println("Active processing");context.setState(new IdleState());}
}class Context {private State current;public void setState(State newState) {this.current = newState;}public void request() {current.handle(this);}
}

观察者模式

定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

解释:观察者模式通过定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

标准实现

// 抽象主题类
abstract class Subject {private List<Observer> observers = new ArrayList<>();public void attach(Observer observer) {observers.add(observer);}public void detach(Observer observer) {observers.remove(observer);}public abstract void notifyObservers();
}// 抽象观察者类
interface Observer {void update();
}// 具体主题类
class ConcreteSubject extends Subject {private String state;public void setState(String state) {this.state = state;notifyObservers();}public String getState() {return state;}public void notifyObservers() {for (Observer observer : observers) {observer.update();}}
}// 具体观察者类
class ConcreteObserver implements Observer {private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject) {this.subject = subject;}public void update() {if (subject.getState().equals("new state")) {System.out.println("ConcreteObserver's reaction");}}
}// 客户端代码
public class Client {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer observer = new ConcreteObserver(subject);subject.attach(observer);subject.setState("new state");}
}
策略模式

定义:定义一系列算法,把它们一个个封装起来,并且使它们可互换。策略模式让算法的变化独立于使用算法的客户。

解释:策略模式通过定义一系列算法,把它们一个个封装起来,并且使它们可互换。策略模式让算法的变化独立于使用算法的客户。

结构解析

  1. 策略接口声明通用操作
  2. 具体策略类实现算法变体
  3. 上下文类维护策略引用并代理执行

Java实现

// 策略接口
interface Strategy {int doOperation(int num1, int num2);
}// 具体策略A
class OperationAdd implements Strategy {public int doOperation(int num1, int num2) {return num1 + num2;}
}// 具体策略B
class OperationSubtract implements Strategy {public int doOperation(int num1, int num2) {return num1 - num2;}
}// 上下文
class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public int executeStrategy(int num1, int num2) {return strategy.doOperation(num1, num2);}
}// 客户端代码
public class Client {public static void main(String[] args) {Context context = new Context(new OperationAdd());System.out.println("Result: " + context.executeStrategy(10, 5));context = new Context(new OperationSubtract());System.out.println("Result: " + context.executeStrategy(10, 5));}
}

访问者模式

定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

解释:访问者模式通过表示一个作用于某对象结构中的各元素的操作,使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

应用场景

  • 对象结构包含多个类
  • 需要动态添加新操作
  • 避免污染元素类接口

Java实现

// 抽象元素
abstract class Element {public abstract void accept(Visitor visitor);
}// 具体元素A
class ConcreteElementA extends Element {public void accept(Visitor visitor) {visitor.visit(this);}public void operationA() {System.out.println("ConcreteElementA operationA");}
}// 具体元素B
class ConcreteElementB extends Element {public void accept(Visitor visitor) {visitor.visit(this);}public void operationB() {System.out.println("ConcreteElementB operationB");}
}// 访问者接口
interface Visitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element);
}// 具体访问者
class ConcreteVisitor implements Visitor {public void visit(ConcreteElementA element) {element.operationA();}public void visit(ConcreteElementB element) {element.operationB();}
}// 客户端代码
public class Client {public static void main(String[] args) {List<Element> elements = new ArrayList<>();elements.add(new ConcreteElementA());elements.add(new ConcreteElementB());Visitor visitor = new ConcreteVisitor();for (Element element : elements) {element.accept(visitor);}}
}
中介者模式

中介者模式提供了一个中介者对象,该对象封装了系统中对象间的交互方式,使各对象不需要显式地相互引用。这样可以减少类间的依赖,从而降低耦合度。

代码示例

// 中介者接口
interface Mediator {void registerComponent(Component component);void relayMessage(Component sender, String message);
}// 具体中介者
class ConcreteMediator implements Mediator {private List<Component> components = new ArrayList<>();@Overridepublic void registerComponent(Component component) {components.add(component);component.setMediator(this);}@Overridepublic void relayMessage(Component sender, String message) {for (Component component : components) {if (component != sender) {component.notify(message);}}}
}// 组件抽象类
abstract class Component {protected Mediator mediator;public void setMediator(Mediator mediator) {this.mediator = mediator;}public abstract void send(String message);public abstract void receive(String message);
}// 具体组件
class UserComponent extends Component {private String name;public UserComponent(String name) {this.name = name;}@Overridepublic void send(String message) {mediator.relayMessage(this, message);}@Overridepublic void receive(String message) {System.out.println(name + " received: " + message);}
}// 客户端代码
public class Client {public static void main(String[] args) {Mediator mediator = new ConcreteMediator();Component user1 = new UserComponent("User1");Component user2 = new UserComponent("User2");mediator.registerComponent(user1);mediator.registerComponent(user2);user1.send("Hello User2!");user2.send("Hi User1!");}
}

迭代器模式

迭代器模式提供了一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

代码示例

// 聚合接口
interface Aggregate {Iterator getIterator();
}// 具体聚合
class ConcreteAggregate implements Aggregate {private List<Object> items = new ArrayList<>();public void addItem(Object item) {items.add(item);}public Object getItem(int index) {return items.get(index);}@Overridepublic Iterator getIterator() {return new ConcreteIterator(this);}
}// 迭代器接口
interface Iterator {boolean hasNext();Object next();
}// 具体迭代器
class ConcreteIterator implements Iterator {private ConcreteAggregate aggregate;private int index = 0;public ConcreteIterator(ConcreteAggregate aggregate) {this.aggregate = aggregate;}@Overridepublic boolean hasNext() {return index < aggregate.items.size();}@Overridepublic Object next() {return aggregate.getItem(index++);}
}// 客户端代码
public class Client {public static void main(String[] args) {Aggregate aggregate = new ConcreteAggregate();aggregate.addItem("Item1");aggregate.addItem("Item2");aggregate.addItem("Item3");Iterator iterator = aggregate.getIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

备忘录模式

备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

代码示例

// 备忘录接口
interface Memento {String getState();
}// 具体备忘录
class ConcreteMemento implements Memento {private String state;public ConcreteMemento(String state) {this.state = state;}@Overridepublic String getState() {return state;}
}// 发起人
class Originator {private String state;public void setState(String state) {this.state = state;}public String getState() {return state;}public Memento saveStateToMemento() {return new ConcreteMemento(state);}public void getStateFromMemento(Memento memento) {state = memento.getState();}
}// 管理者
class Caretaker {private List<Memento> mementoList = new ArrayList<>();public void add(Memento state) {mementoList.add(state);}public Memento get(int index) {return mementoList.get(index);}
}// 客户端代码
public class Client {public static void main(String[] args) {Originator originator = new Originator();originator.setState("State1");Caretaker caretaker = new Caretaker();caretaker.add(originator.saveStateToMemento());originator.setState("State2");caretaker.add(originator.saveStateToMemento());originator.getStateFromMemento(caretaker.get(0));System.out.println(originator.getState()); // 输出:State1}
}

以上是设计模式的分类及说明,包括定义、解释和代码示例。这些模式在实际软件开发中有着广泛的应用,可以帮助开发者解决各种设计问题,提高代码的可维护性和可扩展性。

相关文章:

设计模式的原理及深入解析

创建型模式 创建型模式主要关注对象的创建过程&#xff0c;旨在通过不同的方式创建对象&#xff0c;以满足不同的需求。 工厂方法模式 定义&#xff1a;定义一个创建对象的接口&#xff0c;让子类决定实例化哪一个类。 解释&#xff1a;工厂方法模式通过定义一个创建对象的…...

kotlin flow的两种SharingStarted策略的区别

一 两种 SharingStarted 策略的区别&#xff1a; SharingStarted.Eagerly: 立即开始收集上游流&#xff0c;即使没有下游订阅者持续保持活跃状态&#xff0c;直到 ViewModel 被清除优点&#xff1a;响应更快&#xff0c;数据始终保持最新缺点&#xff1a;消耗更多资源&#x…...

BGP综合实验(2)

一、实验需求 1、实验拓扑图 2、实验需求 使用 PreVal 策略&#xff0c;让 R4 经 R2 到达 192.168.10.0/24 。 使用 AS_Path 策略&#xff0c;让 R4 经 R3 到达 192.168.11.0/24 。 配置 MED 策略&#xff0c;让 R4 经 R3 到达 192.168.12.0/24 。 使用 Local Preference 策…...

python使用jsonpath-ng库操作json数据

jsonpath-ng 库的详细使用如下&#xff1a; 一、安装与导入 安装 通过 pip 安装库&#xff1a; pip install jsonpath-ng支持 Python 3.6 及以上版本。 导入核心模块 主要使用 parse 函数和 JSONPath 对象&#xff1a; from jsonpath_ng import parse二、基础查询操作 1. 简单…...

通用简洁工作汇报项目评估营销策划工作总结年终汇报PPT模版8套一组分享

工作总结汇报PPT模版8套一组分享&#xff1a;工作总结汇报PPT模版分享https://pan.quark.cn/s/04b7ab7a47c4 第一套PPT模版&#xff0c;主要是黄色和灰色调&#xff0c;上方有大面积黄色不规则形状背景&#xff0c;有“POWERPOINT”和“XXXXPPT模版”字样&#xff0c;左侧是黑…...

掌握Git:版本控制与高效协作指南

一、初始Git 提出问题&#xff1a;无论是在工作还是学习&#xff0c;我们在编写各种文档的时候&#xff0c;更改失误&#xff0c;失误后恢复到原来版本&#xff0c;不得不复制出一个副本。 每个版本由各自的内容&#xff0c;但最终只有一个报告需要被我们使用。 但在此之前的…...

ubuntu下配置vscode生成c_cpp_properties.json

-------------学习记录--------------- 在ubuntu下使用vscode时发现cpp文件无法读到头文件&#xff0c;明明头文件在合适的路径下&#xff0c;由于没有制定头文件的路径造成的这个问题。用这篇文章进行简单记录解决方法 ctrlshiftp打开命令面板&#xff0c;也可以点击左上角, …...

Qt读取Excel文件的技术实现与最佳实践

目录 一、成果展示二、核心方法及原理1. QAxObject&#xff08;基于COM接口&#xff09;2. 第三方库QXlsx3. ODBC数据库驱动 三、实现步骤详解1. QAxObject读取Excel&#xff08;需安装Excel/WPS&#xff09;2. QXlsx读取Excel&#xff08;跨平台方案&#xff09; 四、技术选型…...

双条件拆分工作表,一键生成独立工作簿-Excel易用宝

你是否遇到过这样的崩溃瞬间&#xff1f;面对一张密密麻麻的销售数据表&#xff0c;需要按指定维度拆分成工作簿和工作表&#xff0c;而你却只能手动复制粘贴到不同工作簿、工作表&#xff0c;改一个字段就花半小时&#xff0c;数据量大时甚至要熬夜加班&#xff1f; 别担心&a…...

iOS 蓝牙开发中的 BT 与 BLE

在 iOS 开发者的语境里,大家把 BT 和 BLE 当成两种不同的蓝牙技术在谈——它们来自同一个 Bluetooth 规范,但面向的场景、协议栈乃至 Apple 提供的 API 都截然不同。 缩写全称 / 技术名称规范层叫法iOS 支持现状典型用途BTBluetooth Classic(经典蓝牙)又叫 BR/EDR(Basic R…...

TCP和套接字SSL加密连接行为分析

目录 一、前言 二、背景 三、参数介绍 3.1、 have_openssl 3.2、have_ssl 3.3、require_secure_transport 四、--ssl-modemode 五、CREATE USER SSL/TLS选项 六、问题验证 6.1、使用套接字连接 6.2、使用TCP连接 七、分析与总结 一、前言 SSL&#xff08;Secure S…...

kafka 问与答

kafka Q&A How does the client connect to kafka and discovery the brokers. client 只需要知道一部分nodes(brokers)的地址既可以&#xff0c;client 会自动发现剩下的所有topic partition leader nodes, 然后连接上。 When a client connects:It uses the bootstrap…...

docker默认存储迁移

在容器化场景下默认存储路径为&#xff08;/var/lib/docker&#xff09;大多数平台根目录不支持系统盘扩容&#xff0c;会有空间不足风险隐患&#xff0c;因未配置持久化存储导致容器数据丢失。以迁移Docker存储路径至大容量/data目录说明 一、停止容器 systemctl stop docke…...

Ubuntu20.04系统下使用交叉编译工具链(aarch、x86)交叉编译opencv4.5.0

文章目录 0. 引言1. 准备交叉编译工具链2. 安装依赖工具3. 下载 OpenCV 源码4. 创建交叉编译工具链文件5. 配置 CMake 构建6. 构建 OpenCV7. 安装 OpenCV8. 验证9. 问题及解决办法 0. 引言 Ubuntu20.04系统下使用交叉编译工具链&#xff08;aarch、x86&#xff09;交叉编译ope…...

R语言数据可视化

R note book 文档–输出html格式文档&#xff0c;plotly不能生成PDF文件 --- title: "R语言数据可视化" output: html_notebook ---在R语言中进行数据可视化是数据分析和呈现的重要环节&#xff0c;R提供了多种强大的绘图系统和工具。以下是常见的数据可视化方法和示…...

NLP学习路线图(一): 线性代数(矩阵运算、特征值分解等)

引言&#xff1a;语言与矩阵的奇妙邂逅 在自然语言处理&#xff08;NLP&#xff09;的魔法世界里&#xff0c;每个词语都像被施了变形术的精灵&#xff0c;在数学的殿堂中翩翩起舞。当我们用"king - man woman queen"这样的向量魔法破解语义密码时&#xff0c;线性…...

【滑动窗口】LeetCode 1004题解 | 最大连续1的个数 Ⅲ

最大连续1的个数 Ⅲ 一、题目链接二、题目三、题目解析四、算法原理解法一&#xff1a;暴力枚举 zero计数器解法二&#xff1a;滑动窗口 五、编写代码六、时空复杂度 一、题目链接 最大连续1的个数 Ⅲ 二、题目 三、题目解析 注意题目中说的是最多k次&#xff0c;在一个数组…...

Linux 内核等待机制详解:prepare_to_wait_exclusive 与 TASK_INTERRUPTIBLE

1. prepare_to_wait_exclusive 函数解析 1.1 核心作用 prepare_to_wait_exclusive 是 Linux 内核中用于将进程以独占方式加入等待队列的关键函数,其主要功能包括: 标记独占等待:通过设置 WQ_FLAG_EXCLUSIVE 标志,表明此等待条目是独占的。 安全入队:在自旋锁保护下,将条…...

分布式数据库TiDB:深度解析原理、优化与架构设计

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【星海网址导航】 一、TiDB架构设计与核心原理 1.1 分布式架构演进 传统分库分表 vs TiDB架构 #mermaid-svg-8I88Hg2AVkzYTb3O {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fi…...

【深度学习基础】损失函数与优化算法详解:从理论到实践

【深度学习基础】损失函数与优化算法详解&#xff1a;从理论到实践 一、引言 1. 损失函数与优化算法在深度学习中的核心作用 在深度学习中&#xff0c;模型训练的本质是通过不断调整参数&#xff0c;使模型输出尽可能接近真实值。这一过程的核心驱动力是损失函数&#xff08;…...

睿抗足球机器人

目录 大框架 战术 Lua脚本语言编辑环境 大框架 策略脚本&#xff08;LUA-官方脚本&#xff09;、决策算法&#xff08;C-自定义&#xff09;、ROS系统 战术 我们研究了场地的长度、宽度、禁区范围、机器人运动速度等等&#xff0c;发现即使 Kicker 点球往极端角度踢&#xf…...

助力DBA技能无缝平迁 | YashanDB携最新成果亮相XCOPS智能运维管理人年会

5 月 16 日&#xff0c;由上海市软件行业协会、上海市计算机行业协会指导&#xff0c; dbaplus社群主办的XCOPS智能运维管理人年会在广州盛大召开&#xff0c;活动汇聚500余名金融、政府、能源、教育、电信、交通等领域的行业专家。深算院崖山数据库受邀参会&#xff0c;系统性…...

服务端安全测试:OWASP ZAP使用

ZAP下载地址:https://www.zaproxy.org/download/ ZAP有两种扫描方式: 1、使用 OpenAPI / Swagger 地址进行扫描 2、ZAP Proxy + Postman 因为业务云没有添加swagger插件所以本次介绍第2种方式。 【第一步】设置 ZAP 的代理端口(默认是 127.0.0.1:8080) 成功安装并打…...

Amazon Q 从入门到精通 – 测试与重构

Amazon Q Developer 是亚马逊推出的一个专为专业开发人员设计的人工智能助手&#xff0c;旨在提升代码开发和管理效率。其主要功能包括代码生成、调试、故障排除和安全漏洞扫描&#xff0c;提供一站式代码服务。 众所周知&#xff0c;在软件开发领域&#xff0c;测试代码是软件…...

[CSS3]属性增强2

空间转换 使用transform属性实现元素在空间内的位移、旋转、缩放等效果 空间: 是从坐标轴角度定义的。x、y 和z三条坐标轴构成了一个立体空间&#xff0c;z轴位置与视线方向相同。空间转换也叫3D转换 空间位移 使用translate实现元素空间位移效果 transform: translate3d(x…...

Go 语言 vs C+Lua(Skynet)游戏服务器方案对比分析

为啥挑这两个呢&#xff1f;因为两种技术分别对应CSP模型和Actor模型&#xff0c;都是经过时间检验的成熟且可靠的并发模型&#xff0c;问了很多地方&#xff0c;经过gpt整理得出如下报告。 从开发效率、运行性能、热更新扩展、云部署与水平扩展能力、多类型游戏支持等五个维度…...

ArcGIS Pro 3.4 二次开发 - 内容

环境&#xff1a;ArcGIS Pro SDK 3.4 .NET 8 文章目录 内容1 工程1.1 创建一个空工程1.2 使用指定名称创建新工程1.3 使用Pro的默认设置创建新工程1.4 使用自定义模板文件创建新工程1.5 使用 ArcGIS Pro 提供的模板创建工程1.6 打开现有工程1.7 获取当前工程1.8 获取当前工程的…...

java每日精进 5.19【Excel 导入导出】

基于 EasyExcel 实现 Excel 的读写操作&#xff0c;可用于实现最常见的 Excel 导入导出等功能。 Excel 导入导出功能涉及前后端协作&#xff0c;后端处理数据查询、文件生成和解析&#xff0c;前端提供用户交互和文件下载/上传界面。以下是全流程解析&#xff0c;分为导出流程…...

基于Elasticsearch的搜索引擎简介

## 一、Elasticsearch简介 Elasticsearch&#xff08;简称ES&#xff09;是一个开源的、分布式、RESTful风格的搜索和数据分析引擎&#xff0c;基于Apache Lucene开发。它能够实现对海量结构化和非结构化数据的实时存储、搜索和分析&#xff0c;广泛应用于全文检索、日志分析、…...

不同类型桥梁的无人机检测内容及技术难度

不同类型桥梁的无人机检测内容及技术难度 无人机桥梁检测的难度因桥梁类型、结构特点和所处环境的不同而存在显著差异。以下是针对梁桥、拱桥、斜拉桥、悬索桥等主要桥梁类型的无人机检测难度分析&#xff1a; 1. 梁桥&#xff08;简支梁、连续梁&#xff09; 检测难度&#x…...

数据结构实验10.1:内部排序的基本运算

文章目录 一&#xff0c;实验目的二&#xff0c;实验内容1. 数据生成与初始化2. 排序算法实现&#xff08;1&#xff09;直接插入排序&#xff08;2&#xff09;二分插入排序&#xff08;3&#xff09;希尔排序&#xff08;4&#xff09;冒泡排序&#xff08;5&#xff09;快速…...

java20

1.List集合 2.数据结构之栈&#xff0c;队列&#xff0c;数组&#xff0c;链表 3.ArrayList集合 4.LinkedList 5.泛型 注意&#xff1a;E...e是指若干个变量...

LLM笔记(九)KV缓存(2)

文章目录 1. 背景与动机2. 不使用 KV Cache 的情形2.1 矩阵形式展开2.2 计算复杂度 3. 使用 KV Cache 的优化3.1 核心思想3.2 矩阵形式展开3.3 计算复杂度对比 4. 总结5. GPT-2 中 KV 缓存的实现分析5.1 缓存的数据结构与类型5.2 在注意力机制 (GPT2Attention) 中使用缓存5.3 缓…...

将 Element UI 表格拖动功能提取为公共方法

为了在多个页面复用表格拖动功能&#xff0c;我们可以将其封装成以下两种形式的公共方法&#xff1a; 方案一&#xff1a;封装为 Vue 指令&#xff08;推荐&#xff09; 1. 创建指令文件 src/directives/tableDrag.js import interact from interactjs;export default {inse…...

项目中把webpack 打包改为vite 打包

项目痛点: 老vu e-cli1创建的项目,项目是ERP系统集成了很多很多管理,本地运行调试的时候,每次修改代码都需要等待3分钟左右的编译时间,严重影响开发效率. 解决方案: 采用vite构建项目工程 方案执行 第一步 使用vite脚手架构件一个项目,然后把build文件自定义的编译逻辑般到…...

Vue3 Element Plus 中el-table-column索引使用问题

在 Element Plus 的 el-table 组件中&#xff0c;使用 scope.index 是不准确的。正确的索引属性应该是 scope.$index。你的代码需要调整为&#xff1a; vue 复制 下载 <el-button type"primary" size"default" text click"onModifyClick(scope…...

盲盒一番赏小程序系统发展:创新玩法激发市场活力

盲盒一番赏小程序系统凭借其创新的玩法&#xff0c;在潮玩市场中脱颖而出&#xff0c;激发了市场的无限活力。它不仅保留了传统一番赏百分百中奖的特点&#xff0c;还结合线上平台的优势&#xff0c;开发出了更多新颖的玩法。 例如&#xff0c;小程序系统设置了赏品回收功能。…...

MySQL故障排查

目录 MySQL 单示例故障排查 故障现象一​ 故障现象二 故障现象三 故障现象四 故障现象五 故障现象六 故障现象七 故障现象八 MySQL主从复制排查 故障现象一 故障现象二 故障现象三 MySQL 优化 硬件方面 关于CPU 关于内存 关于磁盘 MySQL配置文件 核…...

微服务项目->在线oj系统(Java版 - 4)

相信自己,终会成功 目录 B端用户管理 C端用户代码 发送验证码: 验证验证码 退出登录 登录用户信息功能 用户详情与用户编辑 用户竞赛接口 用户报名竞赛 用户竞赛报名接口查询 用户信息列表 ThreadLocalUtil Hutool工具库 常用功能介绍 B端用户管理 进行列表显示与…...

DDoS与CC攻击:谁才是服务器的终极威胁?

在网络安全领域&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;与CC&#xff08;Challenge Collapsar&#xff09;攻击是两种最常见的拒绝服务攻击方式。它们的目标都是通过消耗服务器资源&#xff0c;导致服务不可用&#xff0c;但攻击方式、威胁程度和防御策略存在显…...

旧物回收小程序,一键解决旧物处理难题

在快节奏的现代生活中&#xff0c;我们常常会面临旧物处理的困扰。扔掉觉得可惜&#xff0c;留着又占空间&#xff0c;而且处理起来还十分麻烦。别担心&#xff0c;我们的旧物回收小程序来啦&#xff0c;只需一键&#xff0c;就能轻松解决你的旧物处理难题&#xff01; 这款小…...

uniapp小程序获取手机设备安全距离

utils.js let systemInfo null;export const getSystemInfo () > {if (!systemInfo) {systemInfo uni.getSystemInfoSync();// 补充安全区域默认值systemInfo.safeAreaInsets systemInfo.safeAreaInsets || {top: 0,bottom: 0,left: 0,right: 0};// 确保statusBarHei…...

小程序弹出层/抽屉封装 (抖音小程序)

最近忙于开发抖音小程序&#xff0c;最想吐槽的就是&#xff0c;既没有适配的UI框架&#xff0c;百度上还找不到关于抖音小程序的案列&#xff0c;我真的很裂开啊&#xff0c;于是我通过大模型封装了一套代码 效果如下 介绍 可以看到 这个弹出层是支持关闭和标题显示的&#xf…...

map与set封装

封装map和set一般分为6步&#xff1a; 1.封装map与set 2.普通迭代器 3.const 迭代器 4.insert返回值处理 5.map operator【】 6.key不能修改的问题 一.红黑树的改造 map与set的底层是通过红黑树来封装的&#xff0c;但是map与set的结点储存的值不一样&#xff0c;set只需要存…...

【C语言基础语法入门】通过简单实例快速掌握C语言核心概念

文章目录 1. Hello World&#xff1a;第一个C程序2. 变量与数据类型3. 运算符4. 控制结构4.1 if-else 条件判断4.2 for 循环4.3 while 循环 5. 函数6. 数组7. 指针8. 结构体总结 &#x1f4e3;按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我自己学习的理解&#xff0…...

Manus AI 突破多语言手写识别技术壁垒:创新架构、算法与应用解析

在人工智能领域&#xff0c;手写识别技术作为连接人类自然书写与数字世界的桥梁&#xff0c;一直备受关注。然而&#xff0c;多语言手写识别面临诸多技术挑战&#xff0c;如语言多样性、书写风格差异、数据稀缺性等。Manus AI 作为该领域的领军者&#xff0c;通过一系列创新技术…...

数字图像处理——图像压缩

背景 图像压缩是一种减少图像文件大小的技术&#xff0c;旨在在保持视觉质量的同时降低存储和传输成本。随着数字图像的广泛应用&#xff0c;图像压缩在多个领域如互联网、移动通信、医学影像和卫星图像处理中变得至关重要。 技术总览 当下图像压缩JPEG几乎一统天下&#xff…...

SGLang和vllm比有什么优势?

环境&#xff1a; SGLang vllm 问题描述&#xff1a; SGLang和vllm比有什么优势&#xff1f; 解决方案&#xff1a; SGLang和vLLM都是在大语言模型&#xff08;LLM&#xff09;推理和部署领域的开源项目或框架&#xff0c;它们各自有不同的设计目标和优势。下面我综合目前…...

BeanFactory和FactoryBean的区别

目录 1、Spring-core 2、控制反转&#xff08;IoC&#xff09; 2.1、定义 2.2、实现方式 1、BeanFactory 2、ApplicationContext 3、FactoryBean BeanFactory是容器&#xff0c;管理所有Bean(包括FactoryBean)&#xff0c;FactoryBean是被管理的Bean&#xff0c;只是它有…...

仓颉开发语言入门教程:搭建开发环境

仓颉开发语言作为华为为鸿蒙系统自研的开发语言&#xff0c;虽然才发布不久&#xff0c;但是它承担着极其重要的历史使命。作为鸿蒙开发者&#xff0c;掌握仓颉开发语言将成为不可或缺的技能&#xff0c;今天我们从零开始&#xff0c;为大家分享仓颉语言的开发教程&#xff0c;…...