zoukankan      html  css  js  c++  java
  • 设计模式策略模式和工厂模式结合使用

    • 怎么把策略模式和工厂模式结合起来使用

    如果大家对策略模式和工厂模式不是很了解的话可以先看前面文章
    策略模式:https://www.jianshu.com/p/958281936901
    工厂模式:https://www.jianshu.com/p/9078481e00c6

    大家可能都用过微信支付,在使用微信支付付钱时候:

    1、当我们的付款金额大于我们的余额时,会让我们使用银行卡支付,
    2、余额充足的时候会让我们优先使用余额里面的钱
    扣款策略一:
    余额(blance) >= 付款金额(tradeAmout) 使用余额
    扣款策略二:
    余额(blance) < 付款金额(tradeAmout) 使用银行卡
    很明显这是一个策略模式的实际应用,但是你还记得策略模式的缺陷吗?它的具体策略必须暴露出去,而且还要由上层模块初始化,这不适合,与迪米特法则不符( 迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。注:摘自百度百科,这个迪米特法则下次再细讲)冲突。高层模块对底层模块仅仅在接触层次上,而不应该是耦合关系。问题出了,我们应该想办法解决,正好工厂模式可以帮我们解决这个问题。但是引入工厂模式也有问题,工厂方法要指定一个类,它才能生产对象,我们用枚举来完成。
    首先我们先建两个实体类WxBlance和WxTrade

    import java.math.BigDecimal;
    
    /**
     * @author shuliangzhao
     * @Title: WxBlance
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:50
     */
    public class WxBlance {
    
        //余额
        private BigDecimal blance;
    
        public BigDecimal getBlance() {
            return blance;
        }
    
        public void setBlance(BigDecimal blance) {
            this.blance = blance;
        }
    }
    
    
    import java.math.BigDecimal;
    
    /**
     * @author shuliangzhao
     * @Title: Trade
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:51
     */
    public class WxTrade {
        private BigDecimal tradeAmout;
    
        private String tradeNo;
    
        private BigDecimal userAmout;
    
        public BigDecimal getUserAmout() {
            return userAmout;
        }
    
        public void setUserAmout(BigDecimal userAmout) {
            this.userAmout = userAmout;
        }
    
        public String getTradeNo() {
            return tradeNo;
        }
    
        public void setTradeNo(String tradeNo) {
            this.tradeNo = tradeNo;
        }
    
        public BigDecimal getTradeAmout() {
            return tradeAmout;
        }
    
        public void setTradeAmout(BigDecimal tradeAmout) {
            this.tradeAmout = tradeAmout;
        }
    }
    

    扣款策略接口

    /**
     * @author shuliangzhao
     * @Title: Deduction
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:53
     */
    public interface Deduction {
    
        public boolean exec(WxBlance wxBlance,WxTrade wxTrade);
    }
    

    扣款策略一

    /**
     * @author shuliangzhao
     * @Title: BlanceDeduction
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:54
     */
    public class BlanceDeduction implements Deduction {
        @Override
        public boolean exec(WxBlance wxBlance, WxTrade wxTrade) {
            if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) >= 0) {
                wxTrade.setUserAmout(wxBlance.getBlance());
            }
            return true;
        }
    }
    

    扣款策略二

    /**
     * @author shuliangzhao
     * @Title: IdCardDeduction
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:54
     */
    public class IdCardDeduction implements Deduction {
        @Override
        public boolean exec(WxBlance wxBlance, WxTrade wxTrade) {
            if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) {
                wxTrade.setUserAmout(wxTrade.getTradeAmout());
            }
            return true;
        }
    }
    

    扣款策略封装

    /**
     * @author shuliangzhao
     * @Title: DedutionContext
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/28 23:58
     */
    public class DedutionContext {
    
        private Deduction deduction;
    
        public DedutionContext(Deduction deduction) {
            this.deduction = deduction;
        }
    
        public boolean exec(WxBlance wxBlance,WxTrade wxTrade) {
            return deduction.exec(wxBlance,wxTrade);
        }
    }
    

    典型的策略上下文。策略模式的缺陷把所有策略类都暴露出去,怎么修改呢?使用工厂模式根据映射产生策略对象

    策略枚举

    /**
     * @author shuliangzhao
     * @Title: StrategyEnum
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/29 0:00
     */
    public enum  StrategyEnum {
    
        BlanceDeduction("com.sl.factorystrategy.BlanceDeduction"),
        IdCardDeduction("com.sl.factorystrategy.IdCardDeduction");
        String value = "";
        private StrategyEnum(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return value;
        }
    }
    

    策略工厂

    /**
     * @author shuliangzhao
     * @Title: StrategyFactory
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/29 0:03
     */
    public class StrategyFactory {
    
        public static Deduction getDeduction(StrategyEnum strategyEnum) {
            Deduction deduction = null;
            try {
                deduction = (Deduction)Class.forName(strategyEnum.getValue()).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return deduction;
        }
    }
    

    扣款调用类

    /**
     * @author shuliangzhao
     * @Title: DeductionFacade
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/29 0:06
     */
    public class DeductionFacade {
    
        //扣款
        public static void deduct(WxBlance wxBlance,WxTrade wxTrade) {
            StrategyEnum strate = getStrate(wxBlance, wxTrade);
            Deduction deduction = StrategyFactory.getDeduction(strate);
            deduction.exec(wxBlance,wxTrade);
        }
    
        //获取扣款策略
        private static  StrategyEnum getStrate(WxBlance wxBlance,WxTrade wxTrade) {
            if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) {
                return StrategyEnum.IdCardDeduction;
            }else {
                return StrategyEnum.BlanceDeduction;
            }
        }
    }
    

    调用客户端client

    /**
     * @author shuliangzhao
     * @Title: Client
     * @ProjectName design-parent
     * @Description: TODO
     * @date 2019/5/29 0:10
     */
    public class Client {
    
        public static void main(String[] args) {
            WxTrade wxTrade = new WxTrade();
            wxTrade.setTradeAmout(new BigDecimal("1000"));
            WxBlance wxBlance = new WxBlance();
            wxBlance.setBlance(new BigDecimal("999"));
            DeductionFacade.deduct(wxBlance,wxTrade);
            System.out.println(wxTrade.getUserAmout());
        }
    }
    

    执行结果

     

    小结:
    策略模式:负责对扣款封装,保证两个策略自由切换,以后增加策略也很容易

    工厂模式:修正策略模式必须对外暴露问题,由工厂模式产生一个具体策略对象

  • 相关阅读:
    setTimeout,setInterval你不知道的…
    浏览器console的用法
    命题和命题的否定可以同时成立吗?
    Web云笔记--CSS
    dreamweaver代码提示失效
    游戏平台代表--PS4【推荐】
    Mac上好用的视频播放器有哪些?
    新浪博客“网络繁忙请稍后再试”
    人工智能成功识别“色情暴力”信息??…
    JS查错小工具-三生有幸【推荐】
  • 原文地址:https://www.cnblogs.com/treeshu/p/10959615.html
Copyright © 2011-2022 走看看