设计模式-(状态模式,策略模式,代理模式,责任链模式)

news/2025/2/27 7:47:30

状态模式

概念:

用于管理一个对象在不同状态下的行为变化。它允许对象在内部状态改变时改变其行为,从而让对象看起来像是改变了其类。状态模式的核心思想是将状态封装到独立的类中,每个状态类都定义了在该状态下对象的行为

状态模式主要涉及以下角色:

Context(上下文):定义了客户端需要的接口,并维护一个对当前状态对象的引用。

State(状态接口):定义了一个接口,用于封装与状态相关的行为。

ConcreteState(具体状态类):实现了状态接口,定义了对象在该状态下的具体行为。

应用:

对象的行为依赖于其状态:当对象的行为会随着状态的改变而改变时,状态模式可以将状态和行为封装到独立的类中。

状态转换复杂:当状态转换逻辑复杂时,状态模式可以将状态转换逻辑分散到各个状态类中,简化代码的复杂性。

避免大量的条件判断:通过使用状态模式,可以减少代码中的条件分支语句,使代码更加清晰和易于维护。

代码:
public interface State {
    void handleRequest();
}
public class PlayState implements State {
    @Override
    public void handleRequest() {
        System.out.println("Playing music...");
    }
}

public class PauseState implements State {
    @Override
    public void handleRequest() {
        System.out.println("Music paused...");
    }
}

public class StopState implements State {
    @Override
    public void handleRequest() {
        System.out.println("Music stopped...");
    }
}
public class MusicPlayer {
    private State currentState;

    public MusicPlayer() {
        currentState = new StopState(); // 初始状态为停止
    }

    public void setState(State state) {
        this.currentState = state;
    }

    public void play() {
        setState(new PlayState());
        currentState.handleRequest();
    }

    public void pause() {
        setState(new PauseState());
        currentState.handleRequest();
    }

    public void stop() {
        setState(new StopState());
        currentState.handleRequest();
    }
}
public class StatePatternDemo {
    public static void main(String[] args) {
        MusicPlayer player = new MusicPlayer();

        player.play();   // 输出:Playing music...
        player.pause();  // 输出:Music paused...
        player.play();   // 输出:Playing music...
        player.stop();   // 输出:Music stopped...
    }
}

策略模式

概念:

定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端

策略模式的主要角色包括:

抽象策略(Strategy):定义了所有策略类的公共接口。

具体策略(Concrete Strategy):实现了抽象策略接口,封装了具体的算法。

上下文(Context):持有一个策略对象的引用,并通过该引用调用策略类的方法。

状态模式差异:
  1. 目的不同

    • 策略模式:目的是封装算法或行为,允许客户端在运行时动态选择不同的算法或行为。它的重点是算法的封装和切换。

    • 状态模式:目的是封装对象的状态和行为,允许对象根据其内部状态改变行为。它的重点是状态的管理和转换。

  2. 行为的来源不同

    • 策略模式:行为的选择由客户端决定。客户端根据需要动态设置上下文中的策略。

    • 状态模式:行为的选择由对象的内部状态决定。对象根据其当前状态自动切换行为,客户端通常不需要直接干预。

  3. 状态管理方式不同

    • 策略模式:没有状态转换的概念。客户端显式地设置策略,策略之间没有固定的转换关系。

    • 状态模式:有明确的状态转换逻辑。状态之间的转换通常由上下文类或状态类自身管理。

  4. 类的数量和职责不同

    • 策略模式:策略类的数量通常由算法的数量决定,每个策略类封装一种算法。

    • 状态模式:状态类的数量通常由对象的状态数量决定,每个状态类封装一种状态下的行为。

应用:

当一个类的行为需要根据环境动态改变时。

当需要在多个算法之间切换时。

当系统中存在多种算法,且这些算法可以互换时。

当需要减少条件判断语句(如if-else)时。

代码:
public interface PaymentStrategy {
    void pay(double amount);
}
public class CreditCardPayment implements PaymentStrategy {
    private String cardNumber;

    public CreditCardPayment(String cardNumber) {
        this.cardNumber = cardNumber;
    }

    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using Credit Card: " + cardNumber);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String email;

    public PayPalPayment(String email) {
        this.email = email;
    }

    @Override
    public void pay(double amount) {
        System.out.println("Paid " + amount + " using PayPal: " + email);
    }
}
public class PaymentContext {
    private PaymentStrategy paymentStrategy;

    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public void executePayment(double amount) {
        if (paymentStrategy == null) {
            throw new IllegalStateException("Payment strategy is not set!");
        }
        paymentStrategy.pay(amount);
    }
}
public class Main {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 使用信用卡支付
        context.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
        context.executePayment(100.0);

        // 使用PayPal支付
        context.setPaymentStrategy(new PayPalPayment("user@example.com"));
        context.executePayment(200.0);
    }
}

代理模式

概念:

代理模式是一种结构型设计模式,它通过引入一个代理对象来控制对真实对象的访问,从而可以在不改变真实对象的情况下扩展其功能。代理模式的核心在于通过代理对象间接访问真实对象,同时在访问前后可以添加额外的逻辑,例如权限检查、延迟加载、日志记录等

与装饰器模式区别:
代理模式装饰器模式
核心目的控制对真实对象的访问动态扩展对象的功能
额外逻辑在调用前后添加逻辑(如权限检查、日志记录)增强目标对象的功能
应用场景远程调用、权限控制、缓存、日志记录动态扩展功能、避免类爆炸、功能组合
实现方式客户端通过代理类间接访问真实类客户端通过装饰器类调用目标类的方法

应用:

远程代理:用于访问远程对象,隐藏远程调用的复杂性。

虚拟代理:用于延迟加载资源密集型对象,避免不必要的初始化。

安全代理:用于控制对真实对象的访问权限。

缓存代理:用于缓存真实对象的结果,提高性能。

日志代理:用于在调用真实对象前后记录日志。

代码:
public interface Subject {
    void request();
}
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
public class Proxy implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }

    private void preRequest() {
        System.out.println("Proxy: Logging the time of request.");
    }

    private void postRequest() {
        System.out.println("Proxy: Logging the request complete.");
    }
}
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();
    }
}

责任链模式

概念:

 责任链模式是一种行为型设计模式,其核心思想是将多个处理者(Handler)连接成一条链,请求沿着链传递,直到某个处理者能够处理该请求。这种模式的主要目的是解耦请求的发送者和接收者,使得多个对象都有机会处理请求,而无需明确指定具体的处理者。

应用:

多个对象可以处理同一请求,但具体由哪个对象处理在运行时动态决定。

希望避免请求发送者和接收者之间的强耦合

需要动态调整处理者的顺序

请求处理具有层次性或顺序性,例如日志记录、权限校验、审批流程等。

代码:
抽象处理者(Handler)
public abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(LeaveRequest request);
}
具体处理者(ConcreteHandler)
public class GroupLeader extends Handler {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getNum() <= 1) {
            System.out.println("组长已审批:" + request.getName() + "同学的请假条,请假天数为" + request.getNum() + "天");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("无法处理");
        }
    }
}

public class Manager extends Handler {
    @Override
    public void handleRequest(LeaveRequest request) {
        if (request.getNum() <= 3) {
            System.out.println("经理已审批:" + request.getName() + "同学的请假条,请假天数为" + request.getNum() + "天");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        } else {
            System.out.println("无法处理");
        }
    }
}

public class GeneralManager extends Handler {
    @
Override    public void handleRequest(LeaveRequest request) {
        System.out.println("总经理已审批:" + request.getName() + "同学的请假条,请假天数为" + request.getNum() + "天");
    }
}
请假请求类
public class LeaveRequest {
    private String name;
    private int num;
    private String content;

    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }
}
public class Client {
    public static void main(String[] args) {
        Handler groupLeader = new GroupLeader();
        Handler manager = new Manager();
        Handler generalManager = new GeneralManager();

        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);

        LeaveRequest request1 = new LeaveRequest("小明", 2, "事假");
        groupLeader.handleRequest(request1);

        LeaveRequest request2 = new LeaveRequest("小红", 5, "病假");
        groupLeader.handleRequest(request2);

//
//经理已审批:小明同学的请假条,请假天数为2天
//总经理已审批:小红同学的请假条,请假天数为5天
    }
}


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

相关文章

图像处理之图像边缘检测算法

目录 1 图像边缘检测算法简介 2 Sobel边缘检测 3 经典的Canny边缘检测算法 4 演示Demo 4.1 开发环境 4.2 功能介绍 4.3 下载地址 参考 1 图像边缘检测算法简介 图像边缘检测是计算机视觉和图像处理中的基本问题&#xff0c;主要目的是提取图像中明暗变化明显的边缘细节…

微服务架构与传统的单体架构有什么区别?微服务架构(Spring Cloud + Maven)强在哪?

微服务架构与传统的单体架构&#xff08;Spring Boot Maven 项目&#xff09;在设计和实现上有显著差异&#xff0c;主要体现在系统拆分方式、部署模式、技术栈选择、维护成本等方面。以下是具体对比&#xff1a; 1. 架构设计 维度单体架构微服务架构系统拆分所有功能模块集…

千峰React:案例一

做这个案例捏 因为需要用到样式&#xff0c;所以创建一个样式文件&#xff1a; //29_实战.module.css .active{text-decoration:line-through } 然后创建jsx文件&#xff0c;修改main文件&#xff1a;导入Todos&#xff0c;写入Todos组件 import { StrictMode } from react …

【前端基础】Day 2 CSS层叠样式表

目录 1.CSS简历 2.CSS 基础选择器 2.1标签选择器 2.2类选择器 2.3 id选择器 2.4通配符选择器 2.5总结 3.CSS字体属性 字体属性总结 4.CSS文本属性 4.1颜色 4.2对齐文本 4.3装饰文本 4.4文本缩进 4.5行间距 4.6文本属性总结 5.CSS的引入方式 5.1内部样式表 …

36. Spring Boot 2.1.3.RELEASE 中实现监控信息可视化并添加邮件报警功能

1. 创建 Spring Boot Admin Server 项目 1.1 添加依赖 在 pom.xml 中添加 Spring Boot Admin Server 和邮件相关依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-w…

用 DeepSeek 打样!KubeSphere LuBan 用 3 天/3 分钟“干掉”大模型部署焦虑

用 DeepSeek 打样&#xff01;KubeSphere LuBan 用 3 天/3 分钟“干掉”大模型部署焦虑 大模型落地&#xff0c;如何告别“部署焦虑”&#xff1f; DeepSeek-R1 的惊艳表现无需赘述&#xff0c;但企业落地时的高门槛却让许多开发者望而却步——复杂的部署流程、资源调度难题、…

通过返回的key值匹配字典中的value值

需求 页面中上面搜索项有获取字典枚举接口&#xff0c;table表格中也有根据key匹配字典中的value 方案一 需要做到的要求 这里上面下拉列表是一个组件获取的字典&#xff0c;下面也是通过字典匹配&#xff0c;所以尽量统一封装一个函数&#xff0c;每个组件保证最少变动tabl…

Spring Data JPA vs MyBatis:ORM框架如何选择?

在选择ORM框架时&#xff0c;Spring Data JPA和MyBatis是两个常见的选择&#xff0c;它们各有优缺点&#xff0c;适用于不同的场景。以下是两者的对比&#xff0c;帮助你做出选择&#xff1a; 1. Spring Data JPA 优点&#xff1a; 开发效率高&#xff1a;通过简单的接口定义和…