状态模式
概念:
用于管理一个对象在不同状态下的行为变化。它允许对象在内部状态改变时改变其行为,从而让对象看起来像是改变了其类。状态模式的核心思想是将状态封装到独立的类中,每个状态类都定义了在该状态下对象的行为
状态模式主要涉及以下角色:
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):持有一个策略对象的引用,并通过该引用调用策略类的方法。
与状态模式差异:
-
目的不同:
-
行为的来源不同:
-
状态管理方式不同:
-
类的数量和职责不同:
应用:
当一个类的行为需要根据环境动态改变时。
当需要在多个算法之间切换时。
当系统中存在多种算法,且这些算法可以互换时。
当需要减少条件判断语句(如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天
}
}