在软件开发中,行为型设计模式关注对象之间的通信,通过定义对象间的交互方式来实现特定的功能。本文将深入解析三种行为型设计模式:责任链模式、命令模式和迭代器模式,并结合实际案例进行分析。
责任链模式允许将请求沿着处理者链进行传递,直到某个处理者能够处理该请求为止。这种方式避免了请求发送者与具体处理者之间的耦合关系,使得多个对象都有机会处理请求。
Apache Tomcat的编码处理:在处理HTTP请求时,Tomcat通过责任链模式来处理不同的编码问题。
Spring Boot的拦截器和过滤器链:在请求处理过程中,多个拦截器或过滤器按照顺序依次处理请求。
动态决定请求处理者:当请求的处理者不明确,或者由运行时动态决定时,责任链模式非常适用。
Handler(抽象处理者):定义了处理请求的接口,通常包含一个指向下一个处理者的引用。
ConcreteHandler(具体处理者):实现抽象处理者接口,具体处理请求。如果无法处理,则将请求传递给下一个处理者。
以下是一个风控系统的实现案例:
// 请求类
public class Request {
private String requestType;
private int money;
// 省略set和get方法
}
// 风控管理抽象类
public abstract class RiskControlManager {
protected String name;
protected RiskControlManager superior;
public RiskControlManager(String name) {
this.name = name;
}
public void setSuperior(RiskControlManager superior) {
this.superior = superior;
}
public abstract void handlerRequest(Request request);
}
// 初级风控
public class FirstRiskControlManager extends RiskControlManager {
public FirstRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(Request request) {
if (request.getMoney() <= 1000) {
System.out.println("普通操作,输入支付密码即可");
System.out.println(name + ": " + request.getRequestType() + ", 金额:" + request.getMoney() + " 处理完成");
} else {
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
// 中级风控
public class SecondRiskControlManager extends RiskControlManager {
public SecondRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(Request request) {
if (request.getMoney() > 1000 && request.getMoney() < 10000) {
System.out.println("稍大额操作,输入支付密码+短信验证码即可");
System.out.println(name + ": " + request.getRequestType() + ", 金额:" + request.getMoney() + " 处理完成");
} else {
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
// 高级风控
public class ThirdRiskControlManager extends RiskControlManager {
public ThirdRiskControlManager(String name) {
super(name);
}
@Override
public void handlerRequest(Request request) {
if (request.getMoney() >= 10000) {
System.out.println("大额操作,输入支付密码+验证码+人脸识别");
System.out.println(name + ": " + request.getRequestType() + ", 金额:" + request.getMoney() + " 处理完成");
} else {
if (superior != null) {
superior.handlerRequest(request);
}
}
}
}
// 使用
public static void main(String[] args) {
RiskControlManager firstControlManager = new FirstRiskControlManager("初级风控");
RiskControlManager secondControlManager = new SecondRiskControlManager("中级风控");
RiskControlManager thirdControlManager = new ThirdRiskControlManager("高级风控");
firstControlManager.setSuperior(secondControlManager);
secondControlManager.setSuperior(thirdControlManager);
Request request1 = new Request();
request1.setRequestType("TRANSFER");
request1.setMoney(20000);
firstControlManager.handlerRequest(request1);
}
降低耦合度:客户端无需知道具体的处理者,只需将请求发送到责任链上。
动态调整:可以通过改变链的顺序动态地新增或删除处理类。
符合开闭原则:可以方便地增加新的处理类,而无需修改现有代码。
性能问题:如果链路较长,可能会对系统性能产生一定影响。
调试困难:在调试时,由于责任链的动态性,可能会增加调试的复杂性。
命令模式将请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化。命令模式属于行为型模式,它将请求的发送者和接收者解耦。
GUI应用程序:如按钮点击事件、菜单操作等。
智能家居控制:通过命令模式可以将不同的操作封装为命令对象。
Command(抽象命令):定义了执行操作的接口。
ConcreteCommand(具体命令):实现抽象命令接口,绑定一个接收者,并调用接收者的操作。
Receiver(接收者):知道如何实施与执行一个请求相关的操作。
Invoker(请求者):要求命令对象执行请求。
Client(客户端):创建一个具体命令对象并设定其接收者。
以下是一个智能家居控制的实现案例:
// 接收者
public class ConditionReceiver {
public void on() {
System.out.println("空调开启了");
}
public void off() {
System.out.println("空调关闭了");
}
public void cool() {
System.out.println("空调开始制冷");
}
public void warm() {
System.out.println("空调开始制暖");
}
}
// 抽象命令
public interface Command {
void execute();
}
// 具体命令:开启空调
public class OnCommand implements Command {
private ConditionReceiver receiver;
public OnCommand(ConditionReceiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.on();
}
}
// 具体命令:关闭空调
public class OffCommand implements Command {
private ConditionReceiver receiver;
public OffCommand(ConditionReceiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.off();
}
}
// 请求者:APP
public class AppInvoker {
private Command onCommand;
private Command offCommand;
public void setOnCommand(Command onCommand) {
this.onCommand = onCommand;
}
public void setOffCommand(Command offCommand) {
this.offCommand = offCommand;
}
public void on() {
onCommand.execute();
}
public void off() {
offCommand.execute();
}
}
// 使用
public static void main(String[] args) {
ConditionReceiver receiver = new ConditionReceiver();
Command onCommand = new OnCommand(receiver);
Command offCommand = new OffCommand(receiver);
AppInvoker appInvoker = new AppInvoker();
appInvoker.setOnCommand(onCommand);
appInvoker.setOffCommand(offCommand);
appInvoker.on();
appInvoker.off();
}
降低耦合度:调用者与接收者之间没有直接依赖关系。
扩展性强:可以很容易地添加新的命令类。
命令类过多:可能会导致系统中存在大量的命令类。
迭代器模式提供了一种方法顺序访问一个聚合对象中的各个元素,而无需暴露该对象的内部实现。迭代器模式属于行为型模式,广泛应用于集合操作中。
集合遍历:如Java中的List
、Set
、Map
等集合都提供了迭代器。
自定义集合:当需要对自定义集合进行遍历时,可以实现迭代器模式。
Aggregate(抽象聚合):定义了创建具体迭代器的接口。
ConcreteAggregate(具体聚合):实现抽象聚合接口,返回一个具体迭代器。
Iterator(抽象迭代器):定义了访问和遍历元素的接口。
ConcreteIterator(具体迭代器):实现抽象迭代器接口,记录遍历中的当前位置。
以下是一个自定义集合容器的实现案例:
// 抽象迭代器
public interface Iterator {
Object next();
boolean hasNext();
}
// 具体迭代器
public class ConcreteIterator implements Iterator {
private List list;
private int index = 0;
public ConcreteIterator(List list) {
this.list = list;
}
@Override
public Object next() {
Object obj = null;
if (this.hasNext()) {
obj = this.list.get(index);
index++;
}
return obj;
}
@Override
public boolean hasNext() {
return index < list.size();
}
}
// 抽象聚合
public interface ICollection {
void add(Object obj);
void remove(Object obj);
Iterator iterator();
}
// 具体聚合
public class MyCollection implements ICollection {
private List list = new ArrayList();
@Override
public void add(Object obj) {
list.add(obj);
}
@Override
public void remove(Object obj) {
list.remove(obj);
}
@Override
public Iterator iterator() {
return new ConcreteIterator(list);
}
}
// 使用
public static void main(String[] args) {
ICollection collection = new MyCollection();
collection.add("小滴课堂老王");
collection.add("小滴课堂Anna小姐姐");
collection.add("小滴课堂二当家小D");
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
System.out.println(obj);
}
}
封装性:不暴露集合的内部结构,同时允许外部代码透明地访问集合内部的数据。
灵活性:支持以不同的方式遍历一个聚合对象。
性能问题:对于简单的遍历(如数组或有序列表),使用迭代器可能会增加额外的开销。
并发问题:在遍历的同时更改迭代器所在的集合结构可能会导致异常。
行为型设计模式在软件开发中具有重要的作用,责任链模式、命令模式和迭代器模式是其中的典型代表。责任链模式通过定义责任链,降低了请求发送者与接收者之间的耦合关系;命令模式通过封装请求,实现了调用者与接收者之间的解耦;迭代器模式通过定义迭代器,实现了对集合的透明访问。在实际开发中,合理运用这些设计模式,可以提高代码的可维护性和可扩展性,降低系统的复杂度。