行业知识
设计模式--策略模式和责任链模式
2026-10-21 11:09:26
来源:互联网转载
策略模式
���略模式(Strategy Pattern)又叫做政策模式,它是将定义的算法家族、分别包装起来,让它们之间可以相互替换,从而让算法的变化不会影响到使用算法的用户。属于行为型模式。
()策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。
应用场景:
()- 针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
- 算法需要自由切换的场景;
- 需要屏蔽算法规则的场景;
/** * 促销策略抽象 */interface IPromotionStrategy{ void doPromotion();}class CouponbuyStrategy implements IPromotionStrategy{ @Override public void doPromotion() { System.out.println("使用优惠卷抵扣"); }}class CashbackStrategy implements IPromotionStrategy{ @Override public void doPromotion() { System.out.println("返现"); }}class EmptyStrategy implements IPromotionStrategy{ @Override public void doPromotion() { System.out.println("无优惠"); }}class PromotionActivity{ private IPromotionStrategy strategy; public PromotionActivity(IPromotionStrategy strategy) { this.strategy = strategy; } public void excute(){ strategy.doPromotion(); }}public class Test { public static void main(String[] args) { PromotionActivity activity618 = new PromotionActivity(new CouponbuyStrategy()); PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy()); activity618.excute(); activity1111.excute(); }}//public class Test {// public static void main(String[] args) {// PromotionActivity activity = null;//// String promotionKey = "COUPON";//// if(promotionKey.equals("COUPON")){// activity = new PromotionActivity(new CouponbuyStrategy());// }else if(promotionKey.equals("CASHBACK")){// activity = new PromotionActivity(new CashbackStrategy());// }//// activity.excute();// }//}我们可以结合单例模式和工厂模式优化上述代码:
class PromotionStrategyFactory{ private static Map PROMOTIONS = new HashMap(); private interface PromotionKey{ String COUPON = "COUPON"; String CASHBACK = "CASHBACK"; } static { PROMOTIONS.put(PromotionKey.COUPON,new CouponbuyStrategy()); PROMOTIONS.put(PromotionKey.CASHBACK,new CashbackStrategy()); } private static final IPromotionStrategy EMPTY = new EmptyStrategy(); private PromotionStrategyFactory(){} public static IPromotionStrategy getPromotionStrategy(String promotionKey){ IPromotionStrategy strategy = PROMOTIONS.get(promotionKey); return strategy==null?EMPTY:strategy; } public static Set getPromotionKeys(){ return PROMOTIONS.keySet(); }}public class Test { public static void main(String[] args) { String promotionKey = "COUPON"; IPromotionStrategy promotionStrategy = PromotionStrategyFactory.getPromotionStrategy(promotionKey); promotionStrategy.doPromotion(); }}策略模式的优缺点:
优点:
- 策略模式符合开闭原则
- 避免使用多重条件转移语句,如if..else...语句、switch语句
- 使用策略模式可以提高算法的保密性和安全性
缺点
- 客户端必须知道所有的策略,并且自行决定使用哪个策略类
- 代码中会产生非常多策略类,增加维护难度。
责任链模式
责任链模式(Chain of Responsibility Pattern)是将链中每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象。当一个请求从链式的首端出发时,会沿着链的路径依次传递给每一个对象,直至有对象处理这个请求为止。属于行为模式。
责任链模式主要是解耦了请求与处理,客户只需要将请求发送到链上即可,无需关心请求的具体内容和处理细节,请求会自动进行传递直至有节点对象进行处理。适用于以下应用场景:
- 多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定;
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
- 可动态指定一组对象处理请求。
利用责任链模式进行数据校验拦截:
import lombok.Data;import org.junit.platform.commons.util.StringUtils;@Dataclass Member{ private String loginName; private String loginPass; private String roleName; public Member(String loginName, String loginPass) { this.loginName = loginName; this.loginPass = loginPass; }}/** * 臃肿的代码 */class MemberService{ public void login(String loginName,String loginPass){ if(StringUtils.isBlank(loginName) || StringUtils.isBlank(loginPass)){ System.out.println("登录信息不能为空"); } Member member = checkExists(loginName,loginPass); if(member == null){ System.out.println("用户不存在"); } if(!"管理员" .equals(member.getRoleName())){ System.out.println("用户权限不够"); } System.out.println("登录成功"); } private Member checkExists(String loginName, String loginPass){ Member member = new Member(loginName,loginPass); member.setRoleName("管理员"); return member; }}/** * 利用责任链优化代码 */abstract class Handler{ protected Handler chain; public void next(Handler handler){ this.chain = handler; } public abstract void doHandle(Member member);}/** * 为空校验 */class ValidateHandler extends Handler{ @Override public void doHandle(Member member) { if(StringUtils.isBlank(member.getLoginName()) || StringUtils.isBlank(member.getLoginPass())){ System.out.println("登录信息不能为空"); return; } chain.doHandle(member); }}class LoginHandler extends Handler{ @Override public void doHandle(Member member) { /** * 查询用户是否存在 */ System.out.println("登录成功"); member.setRoleName("管理员"); chain.doHandle(member); }}/** * 权限验证 */class AuthHandler extends Handler{ @Override public void doHandle(Member member) { if(!"管理员".equals(member.getRoleName())){ System.out.println("权限不够"); return; } System.out.println("登录成功"); }}class MemberService2{ public void login(String loginName,String loginPass){ ValidateHandler validateHandler = new ValidateHandler(); LoginHandler loginHandler = new LoginHandler(); AuthHandler authHandler = new AuthHandler(); validateHandler.next(loginHandler); loginHandler.next(authHandler); validateHandler.doHandle(new Member(loginName,loginPass)); }}public class Test { public static void main(String[] args) { MemberService memberService = new MemberService(); memberService.login("tom","666"); MemberService2 memberService2 = new MemberService2(); memberService2.login("tom","666"); }}另外,链式的组装过于复杂,可以建造者模式处理节点对象进行自动链式组装。处理节点对象顺序不同,构造出来的链式结构也随之不同。修改后的代码:
/** * 利用责任链优化代码 */abstract class Handler{ protected Handler chain; public void next(Handler handler){ this.chain = handler; } public abstract void doHandle(Member member); public static class Builder{ private Handler head; private Handler tail; public Builder addHandler(Handler handler){ if(this.head == null){ this.head = this.tail = handler; return this; } this.tail.next(handler); this.tail=handler; return this; } public Handler build(){ return this.head; } }}class MemberService2{ public void login(String loginName,String loginPass){// ValidateHandler validateHandler = new ValidateHandler();// LoginHandler loginHandler = new LoginHandler();// AuthHandler authHandler = new AuthHandler();//// validateHandler.next(loginHandler);// loginHandler.next(authHandler);//// validateHandler.doHandle(new Member(loginName,loginPass)); Handler.Builder builder = new Handler.Builder(); builder.addHandler(new ValidateHandler()) .addHandler(new LoginHandler()) .addHandler(new AuthHandler()); builder.build().doHandle(new Member(loginName,loginPass)); }}责任链模式的优缺点:
优点:
- 将请求与处理解耦
- 请求处理者只需关注自己感兴趣的请求进行处理,对于不感兴趣的请求,直接转发给下一级节点对象。
- 具备链式传递处理请求功能,请求发送者无需知晓链路结构,只需等待请求处理结果;
- 链路结构灵活,可以通过改变链路结构动态地新增或删除责任
- 易于扩展新的请求处理类,符合开闭原则
缺点:
- 责任链太长或者处理时间过长,会影响整体性能
- 如果节点对象存在循环引用时,会造成***循环,导致系统崩溃。