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

状态模式

概念:

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

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

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

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

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

应用:

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

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

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

代码:
java 复制代码
public interface State {
    void handleRequest();
}
java 复制代码
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...");
    }
}
java 复制代码
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();
    }
}
java 复制代码
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)时。

代码:
java 复制代码
public interface PaymentStrategy {
    void pay(double amount);
}
java 复制代码
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);
    }
}
java 复制代码
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);
    }
}
java 复制代码
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);
    }
}

代理模式

概念:

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

与装饰器模式区别:

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

应用:

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

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

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

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

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

代码:
java 复制代码
public interface Subject {
    void request();
}
java 复制代码
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
java 复制代码
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.");
    }
}
java 复制代码
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();
    }
}

责任链模式

概念:

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

应用:

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

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

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

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

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

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

    public abstract void handleRequest(LeaveRequest request);
}
具体处理者(ConcreteHandler)
java 复制代码
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() + "天");
    }
}
请假请求类
java 复制代码
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;
    }
}
java 复制代码
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天
    }
}
相关推荐
萧萧玉树3 分钟前
设计模式的引入
设计模式
工一木子7 分钟前
【HeadFirst系列之HeadFirst设计模式】第13天之代理模式:控制对象访问的利器!
设计模式·代理模式
多多*5 小时前
设计模式 工厂模式 工厂方法模式 抽象工厂模式
设计模式·工厂方法模式·抽象工厂模式
啥都不懂的小小白6 小时前
Java常见设计模式(上):创建型模式
java·开发语言·设计模式
花王江不语6 小时前
**模式的好处 (设计模式)
开发语言·设计模式
galaa20117 小时前
TypeScript设计模式(4):装饰器模式
设计模式
像污秽一样9 小时前
Java设计模式-基于MVC的WEB设计模式
java·设计模式·mvc
千里码!12 小时前
java23种设计模式-外观模式
设计模式·外观模式
码熔burning12 小时前
(十 一)趣学设计模式 之 组合模式!
java·设计模式·组合模式