什么是策略模式(Stategy)?应用场景是什么?

Stategy策略模式:定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。策略模式使得算法可以在不影响到客户端的情况下发生变化,它也被成为政策模式,是一种行为型模式。(项目经理委派程序猿干活时,需要权衡,这个权衡的过程就可以理解为策略模式!)

策略模式的结构:
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。
简单来说就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

策略模式包含以下3个角色:
1)Context(环境类):负责使用算法策略,其中维持了一个抽象策略类的引用实例。
2)Strategy(抽象策略类):所有策略类的父类,为所支持的策略算法声明了抽象方法。=> 既可以是抽象类也可以是接口
3)ConcreteStrategy(具体策略类):实现了在抽象策略类中声明的方法。

背景: 假设现在要设计一个卖水果系统,本系统可能对所有的高级会员提供每单20%的促销折扣;对中级会员提供每单10%的促销折扣;对初级会员没有折扣,以后还有可能推出更多类别的优惠折扣,比如说买满多少折扣多少等等等等……

package Paint;

// 抽象策略(Strategy)角色
public interface MemberStrategy {
    /**
     * 计算水果价格
     * @param booksPrice    原价
     * @return    折后价
     */
    public double calcPrice(double Price);
}
package Paint;
// ConcreteStrategy(具体策略类)
public class PrimaryMemberStrategy implements MemberStrategy {
    @Override
    public double calcPrice(double Price) {
        System.out.println("对于初级会员的没有折扣");
        return Price;
    }
}
package Paint;
// ConcreteStrategy(具体策略类)
public class IntermediateMemberStrategy implements MemberStrategy {
    @Override
    public double calcPrice(double Price) {
        System.out.println("对于中级会员的折扣为10%");
        return Price * 0.9;
    }
}
package Paint;
// ConcreteStrategy(具体策略类)
public class AdvancedMemberStrategy implements MemberStrategy {
    @Override
    public double calcPrice(double Price) {
        System.out.println("对于高级会员的折扣为20%");
        return Price * 0.8;
    }
}
// 具体策略类--实现了在抽象策略类中声明的方法
package Paint;

public class Price {
    // 持有一个具体的策略对象
    private MemberStrategy strategy;

    /**
     * 构造函数,传入一个具体的策略对象
     * 
     * @param strategy
     *            具体的策略对象
     */
    public Price(MemberStrategy strategy) {
        this.strategy = strategy;
    }

    //计算折后价
    public double quote(double Price) {
        return this.strategy.calcPrice(Price);
    }
}

 

package Paint;

public class Client {

    public static void main(String[] args) {
        // 选择并创建需要使用的策略对象
        MemberStrategy strategy = new AdvancedMemberStrategy();
        // 创建环境
        Price price = new Price(strategy);
        // 计算价格
        double quote = price.quote(300);
        System.out.println("最终价格为:" + quote);
    }
}

13566833-032e51affa46cdcf.png

策略模式仅仅封装算法,提供新的算法插入到已有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定在何时使用何种算法,在什么情况下使用什么算法是由客户端决定的。

------- 认识策略模式 -------
策略模式的重心——不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。

算法的平等性——各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。

运行时策略的唯一性——运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。

公有的行为——经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。

这其实也是典型的将代码向继承等级结构的上方集中的标准做法。

13566833-766a6027bedc7997.png

策略模式的优点

1)提供了对开闭原则的完美支持,用户可以在不修改原有系统的基础上选择具体算法或行为,也可以灵活地增加新的算法或行为。

2)避免了多重的if-else条件选择语句,利于系统的维护。

3)提供了一种算法的复用机制,不同的环境类可以方便地复用这些策略类。

策略模式的缺点

1)客户端需要知道所有的策略类,并自行决定使用哪一个策略 => 只适用于客户端了解所有策略算法的情况。

2)将造成系统产生很多的具体策略类,任何细小的变化都将导致系统要增加一个具体策略类 => 类的个数也许会超出预期。

3)无法在客户端同时使用多个策略类 => 客户端每次只能使用一个策略类。

应用场景

1)如果一个系统要动态地在几种算法之间选择其中一种

2)如果有难以维护的多重if-else条件选择语句是为了实现对象的行为
参照:https://www.jianshu.com/p/d4c2b3df3b4d

3)不希望客户知道复杂的与算法有关的数据结构,可以将其封装到策略中 => 提高算法的保密性和安全性!

所以,用策略模式时可以参照这个模式进行:
1、根据消息获取对应策略
InnerCommand instance = innerCommandContext.getInstance(msg);

2、使用执行策略喂给策略执行者
CommandHandler handler = new CommandHandler(instance);

3、策略执行者执行业务/执行策略
handler.process();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值