美文网首页Java基础
Java设计模式——Stategy策略模式

Java设计模式——Stategy策略模式

作者: 莫问以 | 来源:发表于2018-08-31 15:12 被阅读24次

    Stategy策略模式:定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。策略模式使得算法可以在不影响到客户端的情况下发生变化,它也被成为政策模式,是一种行为型模式。

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


    策略模式.png

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

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


    水果系统策略模式.png
    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);
        }
    }
    
    计算结果

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

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

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

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

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

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


    示例.png

    策略模式的优点

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

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

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

    策略模式的缺点

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

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

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

    应用场景

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

    2)如果有难以维护的多重if-else条件选择语句是为了实现对象的行为

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

    相关文章

      网友评论

        本文标题:Java设计模式——Stategy策略模式

        本文链接:https://www.haomeiwen.com/subject/akiswftx.html