设计模式全文
策略模式
- 案例,鸭子有多种,有多个行为
不同种的鸭子,所具有的行为也不同,无法很好地用抽象层统一
- Strategy Pattern,定义算法簇,分别封装,让算法之间可以相互替换,让算法的变化独立于使用算法的客户端
- 把变化的代码从不变的代码中分离出来
- 针对接口编程
- 将继承转换成组合/聚合,少用继承
- 把算法的使用者和提供者解耦
- 案例类图,把每类行为提取出来,作为附属接口,按需实现
- 飞行策略
public interface FlyBehavior {
void fly();
}
- 策略具体实现
public class GoodFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println("GoodFlyBehavior");
}
}
- 鸭子抽象类,聚合了飞行策略
public abstract class Duck {
FlyBehavior flyBehavior;
public abstract void display();
public void fly() {
if (flyBehavior != null) {
flyBehavior.fly();
}
}
}
- 野鸭类,决定具体的飞行策略
public class WildDuck extends Duck{
public WildDuck() {
flyBehavior = new GoodFlyBehavior();
}
@Override
public void display() {
System.out.println("WildDuck");
}
}
Arrays源码
Comparator中使用了策略模式- 匿名类对象,实现了
Comparator接口的策略
Comparator<Integer> comparator = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
if (o1 > o2) {
return -1;
} else {
return 1;
}
};
};
- 将这个策略传入
Arrays.sort(data, comparator);
小结
- 分析对象中变化的部分和不变的部分,对修改关闭,对扩展开放,将算法封装在独立的
Strategy中,利于扩展 - 多用聚合/组合,少用继承,用行为类组合,避免行为的继承
- 策略过多,导致类数目扩大
职责链模式
- 案例,学校采购,不同的金额,需要不同级别的领导来审核
- Chain of Responsibility Pattern,责任链模式,行为型模式,为请求创建一个接受者的处理链,将请求发送者和接受者进行解耦
- 每一个接受者都包含下一个接受者,一个接受者对象不同处理该请求,将请求传给下一个接受者
- 案例类图
- 处理者抽象类
public abstract class Approver {
Approver approver;
String name;
public Approver(String name) {
this.name = name;
}
public void setApprover(Approver approver) {
this.approver = approver;
}
abstract void processRequest(PurchaseRequest purchaseRequest);
}
- 其中一个的实现,在使用时需要设置下一级处理者,避免为空
public class CollegeApprover extends Approver{
public CollegeApprover(String name) {
super(name);
}
@Override
void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice() > 5000 && purchaseRequest.getPrice() <= 10000) {
System.out.println(purchaseRequest.getId() + " - " + name);
} else {
approver.processRequest(purchaseRequest);
}
}
}
- 请求
public class PurchaseRequest {
private int type = 0; //类型
private float price = 0.0f; //金额
private int id = 0; //编号
public PurchaseRequest(int type, float price, int id) {
this.type = type;
this.price = price;
this.id = id;
}
}
SpringMVC中的应用
- SpringMVC处理流程
- 接受request
- 找到对应的HandlerMapping,并得到
HandleExecutionChain和其中的拦截器HandlerInterceptorHandlerInterceptor依次调用preHandle、postHandle、afterCompletion
DispatcherServlet中的doDispatch,也运用到了适配器模式- 获取
HandlerExecutionChain,主要负责请求拦截器的执行和请求处理,本身不处理请求,将请求分配给链上注册的处理器执行,减少了职责链本身与处理逻辑之间的耦合,规范处理流程
维护了
HandlerInterceptor集合,可以向其中注册拦截器
- 调用
applyPreHandle - 拿到
HandlerInterceptor拦截器 - 调用
applyPostHandle - 调用
postHandle interceptorIndex记录了上一轮执行的拦截器,当postHandle返回true,会保存下来,当期间某一个拦截器的postHandle返回false,会倒序调用前面的拦截器的afterCompletion方法applyPreHandle方法中调用的triggerAfterCompletion,调用了afterCompletionprocessDispatchResult最后也会执行afterCompletion- 过程中发生异常后,也会执行
afterCompletion
小结
- 将请求和处理分开,实现解耦,提高灵活性
- 性能会受到影响,要在
Handler设置一个最大节点数量,过长会破坏性能 - 适用于多个对象处理同个请求,多级请求、请加/加薪等审批业务、javaWeb中tomcat对Encoding的处理、拦截器