您当前的位置: 首页 > 

陈橙橙丶

暂无认证

  • 1浏览

    0关注

    107博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式(四):策略模式

陈橙橙丶 发布时间:2020-04-07 20:18:32 ,浏览量:1

定义

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

应用场景

1、假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。 2、一个系统需要动态地在几种算法中选择一种。

优点

1、策略模式符合开闭原则。 2、避免使用多重条件转移语句,如if…else…语句、switch语句 3、使用策略模式可以提高算法的保密性和安全性。

缺点

1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。 2、代码中会产生非常多策略类,增加维护难度。

下面请看案例 模拟一个场景,某商场正在进行活动,活动分为了三种,返现、团购、折扣。客户可以自行选择哪一种优惠。

1.定义一个公共的策略抽象

//优惠策略抽象
public interface PromotionStrategy {
    //优惠活动,公共行为
    void doPromotion();
}

2.分别写出上面三种策略具体行为。

//优惠券活动
public class CouponStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("领取优惠券,所有商品8折优惠");
    }
}
//返现活动
public class CashbackStrtegy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("购满200元,返现20元到支付账号");
    }
}
//团购活动
public class GroupbuyStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("团购活动,满10人享受团购价");
    }
}
//无优惠
public class EmptyStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("没有活动力度!");
    }
}

3.定义活动规则并发布

//活动规则
public class PromotionActivity {

    private PromotionStrategy promotionStrategy;
    
    public PromotionActivity(PromotionStrategy promotionStrategy){
        this.promotionStrategy = promotionStrategy;
    }
    //发布活动
    public void execute(){
        this.promotionStrategy.doPromotion();
    }
}

现在展示两种不同的写法来比较一下。 测试 1.过去使用的写法,首先创建一个对象在,在构造函数中传递一个优惠类型来指定某种优惠。这种显然是最不提倡的。

	//一般写法
    public static void main(String[] args) {
        //优惠券活动
        PromotionActivity activity = new PromotionActivity(new CouponStrategy());
        activity.execute();
        //返现活动
        PromotionActivity activity1 = new PromotionActivity(new CashbackStrtegy());
        activity1.execute();
    }
//输出结果:
领取优惠券,所有商品8折优惠
购满200元,返现20元到支付账号

由于活动的选择是根据不同的需求的对促销策略进行动态选择的,并不会一次执行多个优惠,所以上面那种情况在实际场景中几乎用不着,我们一般会使用以下这种写法。

2.客户选择策略

public static void main(String[] args) {
        PromotionActivity promotionActivity = null;
        //客户选择的优惠类型
        String promotionKey = "COUPON";
        //此处感觉像什么设计模式? ---------》简单工厂
        if(promotionKey.equals("COUPON")){ //优惠券
            promotionActivity = new PromotionActivity(new CouponStrategy());
        }else if(promotionKey.equals("CASHBACK")){ //返现
            promotionActivity = new PromotionActivity(new CashbackStrtegy());
        }
        promotionActivity.execute();
    }
 //输出结果
 //领取优惠券,所有商品8折优惠

这样改写之后,我们满足了业务需求,可以可以根据自己的需求选择不同的优惠策略了。但是也并不是提倡的选择它也存在弊端:随着时间的业务累计,我们的促销活动会越来越多,于是我们每次增加活动时都得不停的修改逻辑和测试,判断的逻辑也会越来越复杂。 如何解决?------》结合单例和工厂模式来解决:有兴趣的朋友可以了解一下本分类下的文章(单例:单例 | 工厂:工厂)

定义一个工厂类,在这里我就不定义接口了,直接写类来模拟 策略工厂PromotionStrategyFactory 类

public class PromotionStrategyFactory {

    //注册式单例
    private static Map PROOTION_STRATEGY_MAP = new HashMap();
    
    //模拟加载资源
    static {
        PROOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategy());
        PROOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashbackStrtegy());
        PROOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupbuyStrategy());
    }
    //构造方法
    private PromotionStrategyFactory(){

    }
    //无活动对象
    private static final  PromotionStrategy NON_PROMOTION = new EmptyStrategy();
    //定义活动类型
    private interface  PromotionKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GROUPBUY = "GROUPBUY";
    }
    //提供对外方法
    public static PromotionStrategy getPromotionStrategy(String promotionkey){
        return  promotionkey == null || promotionkey.equals("") ? NON_PROMOTION: PROOTION_STRATEGY_MAP.get(promotionkey);
    }
}

测试代码

public static void main(String[] args) {
        String promotionKey = "GROUPBUY";
        PromotionActivity promotionActivity =
                new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
        promotionActivity.execute();
        //增加一个优惠
    }

这样优化了之后,每次增加新的活动不会在影响原来的代码逻辑。只需要工厂中进行添加即可。

再来模拟一个在实际开发中遇到的场景。

比如我们在买东西时候的支付时候得选择,可以选择支付宝、微信、京东、银联等方法来选择付款方式,下面我们就来模拟一下此类场景 1.定义一个抽象的类表示是哪一种付款类型对象(支付宝或微信还是京东又或者银联。 - -!不想落下其中一个,显得孤独。) 疑问:为什么定义成抽象类? 答:因为不管是上述其中任何一种支付类型,他们对于顾客来说支付类型都是相似的。扫码->余额是否足够->成功或者失败所以他们是一个公共的动作和相似的逻辑。因此在这定义成抽象类来约束规范和逻辑

//Payment 抽象类。
public abstract class Payment {
    //抽象方法,支付类型
    public abstract String getName();
    //账户余额,方法根据uid查询对应账户余额,在这里就简写了。
    protected abstract double quetyBalance(String uid);
    //支付方法
    public MsgResult pay(String uid,double amount){
        if(quetyBalance(uid) 状态码:500, 支付金额:余额不足, 支付结果:支付失败
欢迎使用【京东白条】
本次交易:499.6, 开始扣款...
支付状态---->状态码:200, 支付金额:支付金额:499.6, 支付结果:支付成功

我们来看一看类图 在这里插入图片描述 到此本篇就介绍介绍了,希望各位看过的伙伴们如果发现了问题能够及时批评指正,在此感谢。

关注
打赏
1648473527
查看更多评论
立即登录/注册

微信扫码登录

0.0411s