Delegate 委派模式和代理模式strategy的区别?策略模式如何实现消除多层if else?(上)

简介: Delegate 委派模式和代理模式strategy的区别?策略模式如何实现消除多层if else?

委派模式


委派模式,可以精简程序逻辑,提升代码的可读性。


委派模式(Delegate Pattern)的基本作用就是负责任务的调用和分配任务。


例如:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据实际情况给每个员工派发工作任务,待员工把工作任务完成之后,再由项目经理汇报工作进度和结果给老板。

1dc618a0ed9580ce8bfa6facb208c08f.png


和代理模式的区别


跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。委派模式在Spring 中应用非常多,常用的DispatcherServlet 其实就是用到了委派模式。


案例


5d4c6812c8535adbb050f4ddf2e1bce8.png

public interface IEmployee {
    void doing(String command);
}


public class EmployeeA implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是员工A,我现在开始干" + command + "工作");
    }
}
```java
public class EmployeeB implements IEmployee {
    @Override
    public void doing(String command) {
        System.out.println("我是员工B,我现在开始干" + command + "工作");
    }
}


public class Leader implements IEmployee {
    private Map<String, IEmployee> targets = new HashMap<>();
    public Leader() {
        targets.put("登录", new EmployeeA());
        targets.put("加密", new EmployeeB());
    }
    @Override
    public void doing(String command) {
        targets.get(command).doing(command);
    }
}


public class Boss {
    public void command(String command, Leader leader) {
        leader.doing(command);
    }
}


测试:


public class DelegateTest {
  public static void main(String[] args) {
  //客户请求(Boss)、委派者(Leader)、被被委派者(Target)
  //委派者要持有被委派者的引用
  //代理模式注重的是过程, 委派模式注重的是结果
  //策略模式注重是可扩展(外部扩展),委派模式注重内部的灵活和复用
  //委派的核心:就是分发、调度、派遣
  //委派模式:就是静态代理和策略模式一种特殊的组合
  new Boss().command("登录",new Leader());
  new Boss().command("加密", new Leader());
  }
}


46a9d80a6e05e4e3b19d57a0ee70bcdf.png


应用场景


手写一个DispatcherServlet: DispatcherServlet根据url分配到对应的controller的method方法就体现了委派模式。

66ba272a0bfc97be54a5fa679e3d5482.png


public class DispatcherServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            doDispatch(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String uri = request.getRequestURI();
        String mid = request.getParameter("mid");
        if ("/getMemberById".equals(uri)) {
            new MemberController().getMemberById(mid);
        } else if ("/getOrderById".equals(uri)) {
            new OrderController().getOrderById(mid);
        } else if ("/logout".equals(uri)) {
            new SystemController().logout();
        } else {
            response.getWriter().write("404 Not Found!!");
        }
    }


public class MemberController {
    public void getMemberById(String mid){
        System.out.println(mid);
    }
}



public class OrderController {
    public void getOrderById(String mid){
    }
}
public class SystemController {
    public void logout(){
    }
}


策略模式


介绍

66ba272a0bfc97be54a5fa679e3d5482.png

策略模式(Strategy Pattern)是指定义了算法家族、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。

1dc618a0ed9580ce8bfa6facb208c08f.png


策略模式的应用场景

1、假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。

2、一个系统需要动态地在几种算法中选择一种。

5d4c6812c8535adbb050f4ddf2e1bce8.png


案例1。


课程经常会有优惠活动,优惠策略会有很多种可能

如:领取优惠券抵扣、返现促销、拼团优惠。下面我们用代码来模拟,首先我们创建一

个促销策略的抽象PromotionStrategy


5d4c6812c8535adbb050f4ddf2e1bce8.png


public interface PromotionStrategy {
    void doPromotion();
}


/**
 * 返现活动
 * Created by HFL
 */
public class CashbackStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("返现促销,返回的金额转到支付宝账号");
    }
}


/**
 * 优惠券
 * 
 */
public class CouponStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("领取优惠券,课程的价格直接减优惠券面值抵扣");
    }
}


/**
 * 无优惠
 *
 */
public class EmptyStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("无促销活动");
    }
}


/**
 * 拼团优惠
 *
 */
public class GroupbuyStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("拼团,满20人成团,全团享受团购价");
    }
}


优惠活动


public class PromotionActivity {
    private PromotionStrategy promotionStrategy;
    public PromotionActivity(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }
    public void execute(){
        promotionStrategy.doPromotion();
    }
}


测试1:


public class PromotionActivityTest {
    public static void main(String[] args) {
        PromotionActivity activity618 = new PromotionActivity(new CouponStrategy());
        PromotionActivity activity1111 = new PromotionActivity(new CashbackStrategy());
        activity618.execute();
        activity1111.execute();
    }


根据前端的条件选择哪种策略方式:


 

public static void main(String[] args) {
        PromotionActivity promotionActivity = null;
        String promotionKey = "CASHBACK";
        if(StringUtils.equals(promotionKey,"COUPON")){
            promotionActivity = new PromotionActivity(new CouponStrategy());
        }else if(StringUtils.equals(promotionKey,"CASHBACK")){
            promotionActivity = new PromotionActivity(new CashbackStrategy());
        }//......
        promotionActivity.execute();
    }


从形式上看,这这个测试类根据条件,类似简单工厂。所以我们可以改成简单工厂的方法优化下:


再写个简单工厂类.用于生产策略类:


public class PromotionStrategyFactory {
    private static Map<String,PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, PromotionStrategy>();
    static {
        PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
    }
    private static final PromotionStrategy NON_PROMOTION = new EmptyStrategy();
    private PromotionStrategyFactory(){}
    public static PromotionStrategy getPromotionStrategy(String promotionKey){
        PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
        return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
    }
    private interface PromotionKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";
    }
}


重写测试类:


public static void main(String[] args) {
        String promotionKey = "GROUPBUY";
        PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
        promotionActivity.execute();
    }
相关文章
|
2月前
|
运维 监控 Kubernetes
Bitnami 替代品:Websoft9 如何接力单服务器多应用时代
Bitnami 曾为开源应用部署带来革命性体验,但随着 Docker 成熟与战略转向云原生,其单机多应用支持逐渐弱化。面对多应用管理分散、资源冲突、运维工具缺失等痛点,Websoft9 应运而生,提供一键部署、统一管理、智能调度等能力,全面优化单服务器多应用运维体验,成为 Bitnami 的理想继任者。
117 0
Bitnami 替代品:Websoft9 如何接力单服务器多应用时代
|
9月前
|
Cloud Native 云栖大会 调度
平行云荣膺"阿里云产品生态伙伴合作攻坚奖""2022云栖科技创新奖"
2022云栖大会在杭州成功举办,平行云作为阿里云重要合作伙伴受邀参会,并凭借“元域电音Club”精彩亮相。会上,平行云荣获“阿里云产品生态伙伴合作攻坚奖”和“2022云栖科技创新奖”两项大奖,彰显其在云化XR领域的卓越贡献与创新实力。平行云为阿里云XR平台提供算力调度、3D实时渲染等服务,助力元宇宙产业云化转型,推动多行业创新业务形态发展。
271 15
|
9月前
|
资源调度 双11 UED
平行云助力“天猫X网易云音乐”两大IP,打造爆款元宇宙云派对
2022年,天猫与网易云音乐联手打造了一场元宇宙“云派对”,通过3D互联网技术,以游戏+演唱会的形式吸引上万名用户参与。平行云LarkXR提供实时云渲染技术支持,解决高并发和互动数据沉淀难题,实现万人同频互动,带来沉浸式购物、游戏、音乐体验,助力品牌长效增长。
200 11
|
8月前
|
安全 图形学
Unity射线检测的“坑”
在 Unity 中,射线检测是常用功能,但也存在一些常见问题。首先是层(Layer)设置问题,如射线忽略某些层或误检测到不期望的层,需正确设置 LayerMask。其次是碰撞体相关问题,包括碰撞体未启用或类型不匹配,确保碰撞体启用并合理设置属性。再者是射线起始点和方向问题,错误的位置或方向计算会导致检测失败,需准确设置起始点和方向。此外,频繁进行射线检测或检测范围过大会影响性能,应减少检测次数并合理设置范围。最后,在多线程中进行射线检测可能导致错误,应避免在非主线程中直接调用射线检测。
|
9月前
|
编解码 定位技术 vr&ar
NETALAND惊艳上线,Paraverse平行云助力元宇宙大玩家网易闪亮登场
网易传媒旗下全新泛娱乐空间NETALAND于2023年5月上线,融合电影级场景与趣味互动,提供沉浸式元宇宙体验。通过与平行云合作,NETALAND实现了轻量化社交、全地图飞行及丰富的定制化功能,支持用户在五大风格场景中自由探索。LarkXR实时云渲染技术确保了流畅的交互体验,并助力采集宝贵的用户行为数据,推动元宇宙内容创新。
257 14
|
9月前
|
调度 vr&ar 图形学
阿里云联合平行云推出云XR平台,支持沉浸式体验应用快速落地
2022年6月,阿里云与平行云联合发布云XR平台,降低云端视觉计算应用开发门槛,加速数字孪生、虚拟人、虚拟现实等XR应用落地。该平台由阿里云提供算力调度服务,平行云全面集成3D实时渲染、音视频编码与推流等服务,支持多终端接入,助力互联网、新零售、社交等行业创新业务形态。开发者可通过SDK轻松接入,实现3D应用快速云化部署,终端用户可享受低延时、高性能的沉浸式体验。
|
11月前
|
Java
如何在 Java 中处理“Broken Pipe”异常
在Java中处理“Broken Pipe”异常,通常发生在网络通信中,如Socket编程时。该异常表示写入操作的另一端已关闭连接。解决方法包括:检查网络连接、设置超时、使用try-catch捕获异常并进行重试或关闭资源。
915 5
|
数据采集 运维 算法
大数据项目管理:从需求分析到成果交付的全流程指南
【4月更文挑战第9天】本文介绍了大数据项目从需求分析到成果交付的全过程,包括需求收集与梳理、可行性分析、项目规划、数据准备与处理、系统开发与集成,以及成果交付与运维。文中通过实例展示了如何进行数据源接入、数据仓库建设、系统设计、算法开发,同时强调了需求理解、知识转移、系统运维的重要性。此外,还提供了Python和SQL代码片段,以说明具体技术实现。在大数据项目管理中,需结合业务和技术,灵活运用这些方法,确保项目的成功执行和价值实现。
3258 1
|
10月前
|
XML Java 数据格式
Spring Boot 开发中的常见失误
本文深入分析了Spring Boot开发中常见的失误,包括不当使用@Component、@ResponseBody、@Autowired注解,以及不良的异常处理和日志记录实践,提供了有效的规避策略,帮助开发者提升代码质量和系统性能。
197 0
|
设计模式 存储 消息中间件
设计模式之美(二)——设计模式
《设计模式之美》是极客时间上的一个代码学习系列,在学习之后特在此做记录和总结。
设计模式之美(二)——设计模式