`

策略模式——strategy

阅读更多

Strategy Pattern

       本文总结《Design Pattern in Java Chap23 Strategy.   以为用户推荐一款烟火制品选择采取不同推荐策略为例。先讲解如果不采用策略模式会怎样,然后将这些代码重构为策略模式。

 

1 、如果不使用策略模式 Customer::getRecommended() 中封装了复杂的策略选择和策略执行流程。 见图一

 

关键代码(choice & execution of various strategies)

    public Firework getRecommended() {

        //1 、如果有促销的烟火制品,从 config/strategy.dat 中取出并返回

        try {

            Properties p = new Properties();

            p.load(ClassLoader.getSystemResourceAsStream ( "config/strategy.dat" ));

            String promotedName = p.getProperty( "promote" );

            if (promotedName != null ) {

                Firework f = Firework.lookup (promotedName);

                if (f != null )

                    return f;

            }

        } catch (Exception ignored) {

            // If resource missing or it failed to load,

            // fall through to the next approach.

            ignored.printStackTrace();

        }

 

        //2 、注册用户使用 Rel8 引擎

        if (isRegistered()) {

            return (Firework) Rel8.advise ( this );

        }

 

        //3 、未注册用户,若是大客户,使用 LikeMyStuff 引擎

        if (isBigSpender()) {

            return (Firework) LikeMyStuff.suggest ( this );

        }

 

        //4 、未注册用户,若是小客户,随意推荐

        return Firework.getRandom ();

    }

 

由以上代码可知,主要有这样几种推荐策略:

         A. config/strategy.dat 中读取指定推荐的烟火制品

         B.Rel8 引擎

         C.LikeMyStuff 引擎

         D. 随机推荐

 

 

2 、使用策略模式 ,对以上代码进行重构

 

       现在,Customer 中的关键代码是:

public static void main(String[] args) {

        Firework recommendation = new Customer2().getRecommended();

        System. out .println(recommendation.toString());

    }

    public Firework getRecommended() {

        Firework recommend = getAdvisor().recommend( this );

        return recommend;

}

    private Advisor getAdvisor() {

        if ( advisor == null ) {

            if ( promotionAdvisor .hasItem())

                advisor = promotionAdvisor ;

            else if (isRegistered())

                advisor = groupAdvisor ;

            else if (isBigSpender())

                advisor = itemAdvisor ;

            else

                advisor = randomAdvisor ;

        }

        return advisor ;

}

可见,我们将策略选择流程封装在getAdvisor() 中了,getAdvisor() 返回一个策略接口Advisor 的子类实例;调用这个被返回的子类实例的recommend() 方法(重写Advisor 中的recommend() 方法),可以得到推荐的Firework 实例。

 

*****************************************************************

*****************************************************************

另外,对于以前写得很松散的以下两种推荐方式,分别写Advisor 子类对其进行封装。封装前如下:

public Firework getRecommended() {

        //1 、如果有促销的烟火制品,从 config/strategy.dat 中取出并返回

        try {

            Properties p = new Properties();

            p.load(ClassLoader.getSystemResourceAsStream ( "config/strategy.dat" ));

            String promotedName = p.getProperty( "promote" );

            if (promotedName != null ) {

                Firework f = Firework.lookup (promotedName);

                if (f != null )

                    return f;

            }

        } catch (Exception ignored) {

            // If resource missing or it failed to load,

            // fall through to the next approach.

            ignored.printStackTrace();

        }

 

        //2 、注册用户使用 Rel8 引擎

 

        //3 、未注册用户,若是大客户,使用 LikeMyStuff 引擎

 

        //4 、未注册用户,若是小客户,随意推荐

        return Firework.getRandom ();

    }

封装后如下:

public class PromotionAdvisor implements Advisor {

    private Firework promoted ;

 

    public PromotionAdvisor() {

        try {

            Properties p = new Properties();           

           p.load(ClassLoader.

              getSystemResourceAsStream ( "config/strategy.dat" ));

            String promotedFireworkName = p.getProperty( "promote" );

            if (promotedFireworkName != null )

                promoted = Firework.lookup (promotedFireworkName);

        } catch (Exception ignored) {

            promoted = null ;

        }

}

    public boolean hasItem() {

        return promoted != null ;

    }

    public Firework recommend(Customer c) {

        return promoted ;

}

}

 

public class RandomAdvisor implements Advisor {

    public Firework recommend(Customer c) {

        return Firework.getRandom ();

    }

}

 

3 、总结

 

    如何记忆策略模式呢:

           (1) 这里有一个概念(策略选择==> customer2.getAdvisor() )、两个实体(策略调用者==> customer2 ; 策略==> advisor接口实例 ):

           (2) 具体细节 是: “策略调用者”调用其“策略选择”customer2.getAdvisor()选择一个具体的advisor接口实例(如groupAdvisor实例)赋予其成员对象advisor;advisor接口提供统一接口方法advisor.recommend()供实际执行某一个“策略”。


  • 描述: 图一
  • 大小: 20.1 KB
  • 描述: 图二
  • 大小: 21.6 KB
  • 大小: 12 KB
分享到:
评论

相关推荐

    行为型——Strategy(策略模式)

    NULL 博文链接:https://quicker.iteye.com/blog/564116

    设计模式代码——c#

    C#设计模式(23种设计模式) 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) ...21. 策略模式(Strategy Pattern) 22. 访问者模式(Visitor Pattern) 23. 状态模式(State Pattern)

    设计模式——策略模式的学习与理解

    策略模式( Strategy Pattern)就是将算法封装到具有共同接口的独立类中,以独立与客户端,客户端可以灵活的使用或替换算法族里面不同的算法,降低了耦合性。这种类型的设计模式属于行为型模式。 这算法体现了几个...

    Strategy-design-pattern-_-model.rar_strategy

    设计模式——策略模式Strategy design pattern _ model

    设计模式精解 译者:熊节 程序员必看书籍之一 part2

    设计模式精解(Design Patterns Explained) ...如何实现关键模式——Strategy(策略)、Observer(观察者)、Bridge(桥接)、Decorator(装饰)等等。 共同点/变化点分析、设计模式以及它们如何帮助理解抽象类。

    设计模式精解-掌握设计模式

    本书从一个新的视角描述面向对象设计,将...\r\n 如何实现关键模式——Strategy(策略)、Observer(观察者)、Bridge(桥接)、Decorator(装饰)等等。\r\n 共同点/变化点分析、设计模式以及它们如何帮助理解抽象类。

    Python设计模式之策略模式实例详解

    本文实例讲述了Python设计模式之策略模式...设计模式——策略模式 策略模式(strategy):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户 ''' #现金收费抽象类 class

    设计模式精解 译者:熊节 程序员必看书籍之一 part1

    设计模式精解(Design Patterns Explained) ...如何实现关键模式——Strategy(策略)、Observer(观察者)、Bridge(桥接)、Decorator(装饰)等等。 共同点/变化点分析、设计模式以及它们如何帮助理解抽象类。

    设计模式可复用面向对象软件的基础.zip

    2.3.3 策略模式 29 2.4 修饰用户界面 29 2.4.1 透明围栏 29 2.4.2 Monoglyph 30 2.4.3 Decorator 模式 32 2.5 支持多种视感标准 32 2.5.1 对象创建的抽象 32 2.5.2 工厂类和产品类 33 2.5.3 Abstract Factory模式 35...

    设计模式--可复用面向对象软件的基础

    5.9 STRATEGY(策略)——对象行为型模式 5.10 TEMPLATE METHOD(模板方法)——类行为型模式 5.11 VISITOR(访问者)——对象行为型模式 5.12 行为模式的讨论 第六章 结论 6.1 设计模式将带来什么 6.2 一套通用的...

    design-pattern-java.pdf

    处理对象的多种状态及其相互转换——状态模式(五) 处理对象的多种状态及其相互转换——状态模式(六) 策略模式-Strategy Pattern 算法的封装与切换——策略模式(一) 算法的封装与切换——策略模式(二) 算法的...

    研磨设计模式之策略模式

     接下来想写写另外一个虽然较简单,但是使用很频繁的模式——策略模式策略模式(Strategy)1 场景问题1.1 报价管理向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的客户要报不同的...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷6

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷8

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷10

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷5

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷3

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷1

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

    java高手真经 (UML建模+设计模式+面向服务架构) 卷2

    pattern/src/behavior/strategy //13.1策略模式 pattern/src/behavior/templatemethod //13.2模板方法模式 pattern/src/behavior/observer //13.3观察者模式 pattern/src/behavior/iterator //13.4迭代子模式 ...

Global site tag (gtag.js) - Google Analytics