设计模式学习(三)

news/2025/2/6 19:59:04 标签: 设计模式, 学习, java

行为模式

职责链模式(Chain of Responsibility Pattern)

定义

它允许多个对象有机会处理请求,从而避免请求的发送者与接收者之间的耦合。职责链模式将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。

职责链模式的角色
  • 处理器接口(Handler):定义处理请求的接口,通常包含一个方法用于处理请求和一个方法用于设置下一个处理器。
  • 具体处理器(Concrete Handler):实现处理器接口,负责处理请求。如果自己不能处理,则将请求传递给下一个处理器。
  • 客户端(Client):创建职责链,并向链上的第一个处理器提交请求。

假设我们有一个审批流程,需要多个级别的审批人(如经理、总监、CEO)来处理请求。我们可以使用职责链模式来实现这个流程。

java">// 处理器接口:审批人
interface Approver {
    void setNextApprover(Approver nextApprover);
    void processRequest(PurchaseRequest request);
}
java">// 具体处理器:经理
class Manager implements Approver {
    private Approver nextApprover;

    @Override
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= 1000) {
            System.out.println("Manager approves the request for $" + request.getAmount());
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 具体处理器:总监
class Director implements Approver {
    private Approver nextApprover;

    @Override
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= 5000) {
            System.out.println("Director approves the request for $" + request.getAmount());
        } else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 具体处理器:CEO
class CEO implements Approver {
    @Override
    public void setNextApprover(Approver nextApprover) {
        // CEO 是最后一个审批人,没有下一个审批人
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= 10000) {
            System.out.println("CEO approves the request for $" + request.getAmount());
        } else {
            System.out.println("Request for $" + request.getAmount() + " requires a board meeting.");
        }
    }
}
java">// 请求类:采购请求
class PurchaseRequest {
    private double amount;

    public PurchaseRequest(double amount) {
        this.amount = amount;
    }

    public double getAmount() {
        return amount;
    }
}
java">public class ChainOfResponsibilityPatternDemo {
    public static void main(String[] args) {
        // 创建审批人
        Approver manager = new Manager();
        Approver director = new Director();
        Approver ceo = new CEO();

        // 设置职责链
        manager.setNextApprover(director);
        director.setNextApprover(ceo);

        // 创建采购请求
        PurchaseRequest request1 = new PurchaseRequest(800);
        PurchaseRequest request2 = new PurchaseRequest(4500);
        PurchaseRequest request3 = new PurchaseRequest(12000);

        // 处理请求
        manager.processRequest(request1);
        manager.processRequest(request2);
        manager.processRequest(request3);
    }
}
jdk或者android系统上的应用
  • Java 异常处理

Java 的异常处理机制是职责链模式的一个典型应用。当一个异常被抛出时,它会沿着调用栈向上传递,直到找到能够处理该异常的 catch 块。

java">try {
    // 可能会抛出异常的代码
} catch (NullPointerException e) {
    System.out.println("Caught NullPointerException");
} catch (Exception e) {
    System.out.println("Caught Exception");
}
  • Android事件分发机制

Android 的事件分发机制是职责链模式的一个典型应用。当用户触摸屏幕时,触摸事件会从 Activity 传递到 ViewGroup,再传递到具体的 View,直到有 View 处理该事件。

java">@Override
public boolean onTouchEvent(MotionEvent event) {
    // 处理触摸事件
    return super.onTouchEvent(event);
}

命令模式(Command Pattern)

定义

它将请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,并支持请求的排队、记录日志、撤销等操作。命令模式的核心思想是将“请求”抽象为一个独立的对象,从而解耦请求的发送者和接收者。

命令模式的角色
  • 命令接口(Command):定义执行操作的接口。
  • 具体命令(Concrete Command):实现命令接口,封装具体的操作。
  • 接收者(Receiver):执行具体操作的对象。
  • 调用者(Invoker):持有命令对象,并调用命令的执行方法。
  • 客户端(Client):创建命令对象并设置其接收者。

假设我们有一个遥控器,可以控制多种家电(如灯、风扇等)。我们可以使用命令模式来实现遥控器的功能。

java">// 命令接口
interface Command {
    //执行命令
    void execute();
}
java">// 具体命令:开灯
class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}

// 具体命令:关灯
class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.off();
    }
}

// 具体命令:开风扇
class FanOnCommand implements Command {
    private Fan fan;

    public FanOnCommand(Fan fan) {
        this.fan = fan;
    }

    @Override
    public void execute() {
        fan.on();
    }
}

// 具体命令:关风扇
class FanOffCommand implements Command {
    private Fan fan;

    public FanOffCommand(Fan fan) {
        this.fan = fan;
    }

    @Override
    public void execute() {
        fan.off();
    }
}
java">// 接收者:灯
class Light {
    public void on() {
        System.out.println("Light is on");
    }

    public void off() {
        System.out.println("Light is off");
    }
}

// 接收者:风扇
class Fan {
    public void on() {
        System.out.println("Fan is on");
    }

    public void off() {
        System.out.println("Fan is off");
    }
}
java">// 调用者:遥控器
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}
java">public class CommandPatternDemo {
    public static void main(String[] args) {
        // 创建接收者
        Light light = new Light();
        Fan fan = new Fan();

        // 创建具体命令
        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);
        Command fanOn = new FanOnCommand(fan);
        Command fanOff = new FanOffCommand(fan);

        // 创建调用者
        RemoteControl remote = new RemoteControl();

        // 控制灯
        remote.setCommand(lightOn);
        remote.pressButton(); // 输出: Light is on

        remote.setCommand(lightOff);
        remote.pressButton(); // 输出: Light is off

        // 控制风扇
        remote.setCommand(fanOn);
        remote.pressButton(); // 输出: Fan is on

        remote.setCommand(fanOff);
        remote.pressButton(); // 输出: Fan is off
    }
}
jdk或者android系统上的应用
  • Runnable 接口

Java 的 Runnable 接口是命令模式的一个典型应用。Runnable 封装了一个任务,而 Thread 是调用者,负责执行任务。

java">// 命令接口
Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("Task is running");
    }
};

// 调用者
Thread thread = new Thread(task);
thread.start();
  • Handler 和 Message

在 Android 中,Handler 和 Message 是命令模式的一个典型应用。Message 封装了一个任务,而 Handler 是调用者,负责处理任务。

java">// 命令接口
Message message = Message.obtain(handler, new Runnable() {
    @Override
    public void run() {
        System.out.println("Message is handled");
    }
});

// 调用者
Handler handler = new Handler(Looper.getMainLooper());
handler.sendMessage(message);

解释器模式(Interpreter Pattern)

定义

它定义了一种语言的语法表示,并使用解释器来解释语言中的句子。这种模式通常用于需要解释和执行特定语法规则的场景,例如编译器、正则表达式引擎等。

解释器模式的角色
  • 抽象表达式(AbstractExpression):定义解释操作的接口。
  • 终结符表达式(TerminalExpression):实现与文法中的终结符相关的解释操作。
  • 非终结符表达式(NonterminalExpression):实现与文法中的非终结符相关的解释操作。
  • 上下文(Context):包含解释器需要的全局信息。
  • 客户端(Client):构建抽象语法树并调用解释操作。

假设我们需要解释简单的数学表达式,例如 1 + 2 - 3。我们可以使用解释器模式来实现这个功能。

java">//定义抽象接口
interface Expression {
    int interpret(Context context);
}
java">//定义终结符表达式
class NumberExpression implements Expression {
    private int number;

    public NumberExpression(int number) {
        this.number = number;
    }

    @Override
    public int interpret(Context context) {
        return number;
    }
}
java">//定义非终结符表达式
class AddExpression implements Expression {
    private Expression left;
    private Expression right;

    public AddExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) + right.interpret(context);
    }
}

class SubtractExpression implements Expression {
    private Expression left;
    private Expression right;

    public SubtractExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public int interpret(Context context) {
        return left.interpret(context) - right.interpret(context);
    }
}
java">//定义上下文
class Context {
    // 这里可以包含解释器需要的全局信息
}
java">public class InterpreterPatternDemo {
    public static void main(String[] args) {
        Context context = new Context();

        // 构建表达式:1 + 2 - 3
        Expression expression = new SubtractExpression(
            new AddExpression(new NumberExpression(1), new NumberExpression(2)),
            new NumberExpression(3)
        );

        // 解释并输出结果
        int result = expression.interpret(context);
        System.out.println("Result: " + result);  // 输出: Result: 0
    }
}
jdk或者android系统上的应用

迭代器模式(Iterator Pattern)

定义

它提供了一种顺序访问聚合对象(如列表、集合等)中元素的方法,而不需要暴露其底层表示。迭代器模式将遍历逻辑从聚合对象中分离出来,使得聚合对象和遍历逻辑可以独立变化。

迭代器模式的角色
  • 迭代器接口(Iterator):定义遍历和访问元素的方法。
  • 具体迭代器(ConcreteIterator):实现迭代器接口,负责管理当前遍历的位置。
  • 聚合接口(Aggregate):定义创建迭代器的方法。
  • 具体聚合类(ConcreteAggregate):实现聚合接口,返回一个具体迭代器的实例。

假设我们有一个自定义的集合类 MyCollection,它存储了一组整数。我们希望提供一个迭代器来遍历这个集合中的元素。

  1. 定义迭代器接口
java">interface Iterator<T> {
    boolean hasNext();  // 检查是否还有下一个元素
    T next();           // 返回下一个元素
}
  1. 定义具体迭代器
java">class MyCollectionIterator implements Iterator<Integer> {
    private int[] collection;
    private int position = 0;

    public MyCollectionIterator(int[] collection) {
        this.collection = collection;
    }

    @Override
    public boolean hasNext() {
        return position < collection.length;
    }

    @Override
    public Integer next() {
        if (this.hasNext()) {
            return collection[position++];
        }
        throw new IndexOutOfBoundsException("No more elements");
    }
}
  1. 定义聚合接口
java">interface Aggregate<T> {
    Iterator<T> createIterator();  // 创建迭代器
}
  1. 定义具体聚合类
java">class MyCollection implements Aggregate<Integer> {
    private int[] items;

    public MyCollection(int[] items) {
        this.items = items;
    }

    @Override
    public Iterator<Integer> createIterator() {
        return new MyCollectionIterator(items);
    }
}
java">public class IteratorPatternDemo {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        MyCollection collection = new MyCollection(numbers);

        // 获取迭代器
        Iterator<Integer> iterator = collection.createIterator();

        // 遍历集合
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
迭代器模式的优缺点

优点:

  • 将遍历逻辑与聚合对象分离,符合单一职责原则。
  • 提供了一种统一的方式来遍历不同类型的聚合对象。
  • 支持多种遍历方式(例如正向遍历、反向遍历)。

缺点:

  • 对于简单的集合,使用迭代器可能会增加代码的复杂性。
  • 如果集合的结构发生变化,可能需要修改迭代器的实现。
jdk或者android系统上的应用

Java 的集合框架(如 List、Set、Map)已经内置了迭代器模式。

java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JavaIteratorExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        // 使用 Java 内置的迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

中介者模式(Mediator Pattern)

定义

它通过引入一个中介者对象来封装一组对象之间的交互。中介者模式减少了对象之间的直接依赖,使得对象之间的耦合度降低,从而更容易维护和扩展。

迭代器模式的角色
  • 中介者接口(Mediator):定义对象之间通信的接口。
  • 具体中介者(ConcreteMediator):实现中介者接口,协调各个对象之间的交互。
  • 同事类(Colleague):定义各个对象的接口,每个同事类都知道中介者对象。
  • 具体同事类(ConcreteColleague):实现同事类接口,负责与其他同事类通信。

假设我们有一个聊天室系统,多个用户可以通过聊天室发送消息。聊天室作为中介者,负责将消息从一个用户传递给其他用户。

  1. 定义中介者接口
java">interface ChatMediator {
    void sendMessage(String message, User user);  // 发送消息
    void addUser(User user);                      // 添加用户
}
  1. 定义具体中介者
java">class ChatRoom implements ChatMediator {
    private List<User> users;

    public ChatRoom() {
        this.users = new ArrayList<>();
    }

    @Override
    public void sendMessage(String message, User user) {
        for (User u : users) {
            // 不将消息发送给自己
            if (u != user) {
                u.receive(message);
            }
        }
    }

    @Override
    public void addUser(User user) {
        this.users.add(user);
    }
}
  1. 定义同事类
java">abstract class User {
    protected ChatMediator mediator;
    protected String name;

    public User(ChatMediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public abstract void send(String message);  // 发送消息
    public abstract void receive(String message);  // 接收消息
}
  1. 定义具体同事类
java">class ChatUser extends User {
    public ChatUser(ChatMediator mediator, String name) {
        super(mediator, name);
    }

    @Override
    public void send(String message) {
        System.out.println(this.name + " 发送消息: " + message);
        mediator.sendMessage(message, this);
    }

    @Override
    public void receive(String message) {
        System.out.println(this.name + " 收到消息: " + message);
    }
}
  1. 客户端代码
java">public class MediatorPatternDemo {
    public static void main(String[] args) {
        // 创建中介者(聊天室)
        ChatMediator chatRoom = new ChatRoom();

        // 创建用户
        User user1 = new ChatUser(chatRoom, "Hehe");
        User user2 = new ChatUser(chatRoom, "Bob");
        User user3 = new ChatUser(chatRoom, "Charlie");

        // 将用户添加到聊天室
        chatRoom.addUser(user1);
        chatRoom.addUser(user2);
        chatRoom.addUser(user3);

        // 用户发送消息
        user1.send("大家好!");
        user2.send("你好,Hehe!");
        user3.send("欢迎来到聊天室!");
    }
}

备忘录模式(Memento Design Pattern)

定义

它允许在不暴露对象实现细节的情况下保存和恢复对象的状态。该模式主要用于实现撤销(undo)操作。

备忘录模式的角色
  • 发起人(Originator):创建并恢复备忘录的对象。
  • 备忘录(Memento):存储发起人内部状态的快照,并防止其他对象访问备忘录。备忘录通常只有发起人可以访问其内容。
  • 负责人(Caretaker):负责管理备忘录,但不能查看或修改备忘录的内容。

使用备忘录模式来实现一个文本编辑器的撤销功能。

  1. 发起人(Originator)
java">public class TextEditor {
    private String content;

    public TextEditor(String content) {
        this.content = content;
    }

    public void type(String words) {
        content += words;
    }

    // 创建备忘录
    public Memento saveStateToMemento() {
        return new Memento(content);
    }

    // 从备忘录恢复状态
    public void getStateFromMemento(Memento memento) {
        this.content = memento.getContent();
    }

    public String getContent() {
        return content;
    }
}
  1. 备忘录(Memento)
java">public class Memento {
    private String content;

    // 私有构造函数,防止外部实例化
    private Memento(String content) {
        this.content = content;
    }

    public Memento(TextEditor originator) {
        this.content = originator.getContent();
    }

    public String getContent() {
        return content;
    }
}
  1. 负责人(Caretaker)
java">import java.util.ArrayList;
import java.util.List;

public 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);
    }
}
java">public class Client {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor("Hello");
        Caretaker caretaker = new Caretaker();

        editor.type(" world");
        caretaker.add(editor.saveStateToMemento());

        editor.type("!!!");
        System.out.println("Current Content: " + editor.getContent()); // Hello world!!!

        // 撤销到上一个状态
        editor.getStateFromMemento(caretaker.get(0));
        System.out.println("After Undo: " + editor.getContent()); // Hello world
    }
}

http://www.niftyadmin.cn/n/5843298.html

相关文章

基于Python实现机器视觉与深度学习相结合的项目

以下是一个基于Python实现机器视觉与深度学习相结合的项目&#xff0c;用于对茶汤照片进行背景处理、提取RGB值的详细步骤及代码示例。 整体思路 图像读取与预处理&#xff1a;从采集装置传输到电脑的照片&#xff0c;使用OpenCV库读取图像&#xff0c;并进行灰度转换、高斯模…

MySQL索引类型详解

MySQL 中的索引是提高查询性能的重要工具。不同的索引类型适用于不同的场景&#xff0c;选择合适的索引类型可以显著提升查询效率。以下是 MySQL 中常见索引类型的详细解析。 1. 索引的基本概念 索引是一种数据结构&#xff0c;用于快速查找数据库表中的特定行。MySQL 支持多种…

pycharm集成通义灵码应用

在pycharm中安装通义灵码 1、打开files-settings 2、选中plugins-搜索”TONGYI Lingma“&#xff0c;点击安装 3.安装完成后在pycharm的右侧就有通义灵码的标签 4、登录账号 5、查看代码区域代码&#xff0c;每一个方法前面都多了通义灵码的标识&#xff0c;可以直接选择…

【赵渝强老师】K8s中Pod探针的TCPSocketAction

在K8s集群中&#xff0c;当Pod处于运行状态时&#xff0c;kubelet通过使用探针&#xff08;Probe&#xff09;对容器的健康状态执行检查和诊断。K8s支持三种不同类型的探针&#xff0c;分别是&#xff1a;livenessProbe&#xff08;存活探针&#xff09;、readinessProbe&#…

PHP `foreach` 引用变量导致的问题及其解决方案

PHP foreach 引用变量导致的问题及其解决方案 1. 引言 在 PHP 中&#xff0c;foreach 是用于遍历数组的重要结构。然而&#xff0c;在某些情况下&#xff0c;使用 foreach 的 引用变量&#xff08;&&#xff09; 可能会导致意想不到的错误&#xff0c;尤其是在不同版本的…

tkvue 入门,像写html一样写tkinter

介绍 没有官网&#xff0c;只有例子 安装 像写vue 一样写tkinter 代码 pip install tkvue作者博客 修改样式 import tkvue import tkinter.ttk as ttktkvue.configure_tk(theme"clam")class RootDialog(tkvue.Component):template """ <Top…

【力扣题解】922. 按奇偶排序数组 II

&#x1f60a;博主目前也在学习&#xff0c;有错误欢迎指正&#x1f60a; &#x1f308;保持热爱 奔赴星海&#x1f308; 文章目录 一、题目1、题目描述2、基础框架3、原题链接 二、解题报告1、思路分析2、代码详解 三、本题知识 一、题目 1、题目描述 给定一个非负整数数组 n…

100.2 AI量化面试题:在构建多因子选股模型时,如何有效处理因子之间的共线性问题?

目录 0. 承前1. 共线性问题的基本认识1.1 什么是共线性1.2 共线性的检测方法 2. 共线性处理的主要方法2.1 因子筛选法2.2 因子正交化 3. 高级处理方法3.1 主成分分析(PCA)3.2 因子旋转 4. 实践建议4.1 处理流程建议4.2 效果评估 5. 回答话术 0. 承前 如果想更加全面清晰地了解…