zoukankan      html  css  js  c++  java
  • 设计模式解析(五)——几种设计模式之Strategy

    《设计模式》一书中对Strategy模式的意图叙述如下:

    定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换,Strategy模式使算法可独立于使用它的客户而变化。

    strategy模式以下列原则为基础:

    1.对象都具有职责
    2.这些职责不同的具体实现是通过多态的使用完成的
    3.概念上相同的算法具有多个不同的实现,需要进行管理
     
      Strategy模式:关键特征

    意图

    可以根据所处的上下文,使用不同的业务规划或算法

    问题

    对所需算的选择取决于发出请求的客户或者要处理的数据。如果只有一些不会变化的算法,就不需要Strategy模式。

    解决方案

    将对算法的选择和算法的实现相分离。允许根据上下文进行选择。

    参与者与协作者

    • strategy指定了如何使用不同的算法。
    • 各ConcreteStrategy实现了这些不同的算法。
    • Context通过类型为Strategy的引用使用具体的ConcreteStrategy。Strategy与Context相互作用以实现所选的算(有时候Strategy必须查询Context)。Context将来自Client的请求转发给Strategy。

    效果

    • Strategy模式定义了一系列的算法。
    • 可以不适用switch语句或条件语句。
    • 必须以相同的方式调用所有的算法(它们必须拥有相同的接口)。个ConcreteStrategy与Context之间的相互作用可能需要在Context中加入获取状态的方法。

    实现

    让使用算法的类(Context)包含一个抽象类(Strategy),该抽象类有一个抽象方法指定如何调用算法。每个派生类按照需要实现算法。注意:在原型Strategy模式中,选择所用具有实现的职责由Client对象承担,并转给Strategy模式的Context对象。

    Stategy模式的通用结构图

    Strategy

    Strategy模式会带来爆炸性增长问题的解决方法

    C++

    可以用Strategy抽象类头文件包含所有ConcreteStrategy类的头文件。同时用|Strategy抽象类的cpp文件包含各ConcreteStrategy的代码。

    Java

    可以在Strategy抽象类内使用内部类包含所有的ConcreteStrategy。

    但是如果无法控制所有的Strategy对象,也就是说如果有其它程序员需要实现自己的算法,就不要这么做。

    代码示例:

    TaxController.h
     1 //TaxController.h
     2 #pragma once
     3 #include "CalcTax.h"
     4 
     5 class TaskController
     6 {
     7 public:
     8     TaskController(void);
     9     void process();
    10     CalcTax *getTaxRulesForCountry();
    11 public:
    12     ~TaskController(void);
    13 };
    14 TaxController.cpp
    15 #include "TaskController.h"
    16 #include "SalesOrder.h"
    17 #include "CalcTax.h"
    18 #include "USTax.h"
    19 
    20 TaskController::TaskController(void)
    21 {
    22 }
    23 
    24 TaskController::~TaskController(void)
    25 {
    26 }
    27 
    28 void TaskController::process ()
    29 {
    30     // this code is an emulation of a 
    31     // processing task controller
    32     // . . .
    33     // figure out which country you are in
    34     CalcTax *myTax;
    35     myTax= getTaxRulesForCountry();
    36     SalesOrder *mySO= new SalesOrder();
    37     mySO->process( myTax);
    38 }
    39 
    40 CalcTax *TaskController::getTaxRulesForCountry() 
    41 {
    42     // In real life, get the tax rules based on
    43     // country you are in.  You may have the
    44     // logic here or you may have it in a
    45     // configuration file
    46     // Here, just return a USTax so this 
    47     // will compile.
    48     return new USTax;
    49 }
    SalesOrder.h
     1 //SalesOrder.h
     2 #pragma once
     3 #include "CalcTax.h"
     4 
     5 class SalesOrder
     6 {
     7 public:
     8     SalesOrder(void);
     9     void process (CalcTax *TaxToUse);
    10 public:
    11     ~SalesOrder(void);
    12 };
    13 SalesOrder.cpp
    14 #include "SalesOrder.h"
    15 
    16 SalesOrder::SalesOrder(void)
    17 {
    18 }
    19 
    20 SalesOrder::~SalesOrder(void)
    21 {
    22 }
    23 
    24 void SalesOrder::process (CalcTax *taxToUse)
    25 {
    26     long itemNumber= 0;
    27     double price= 0;
    28 
    29     // given the tax object to use
    30 
    31     // . . .
    32 
    33     // calculate tax
    34     double tax= taxToUse->taxAmount( itemNumber, price);
    35 }
    CalcTax.h
     1 //CalcTax.h
     2 #pragma once
     3 
     4 class CalcTax
     5 {
     6 public:
     7     CalcTax(void);
     8     double virtual taxAmount( long, double)= 0;
     9 public:
    10     ~CalcTax(void);
    11 };
    12 CalcTax.cpp
    13 #include "CalcTax.h"
    14 
    15 CalcTax::CalcTax(void)
    16 {
    17 }
    18 
    19 CalcTax::~CalcTax(void)
    20 {
    21 }
    CanTax.h
     1 //CanTax.h
     2 #pragma once
     3 #include "calctax.h"
     4 
     5 class CanTax :
     6     public CalcTax
     7 {
     8 public:
     9     CanTax(void);
    10     double taxAmount( long, double);
    11 public:
    12     ~CanTax(void);
    13 };
    14 CanTax.cpp
    15 #include "CanTax.h"
    16 
    17 CanTax::CanTax(void)
    18 {
    19 }
    20 
    21 CanTax::~CanTax(void)
    22 {
    23 }
    24 
    25 double CanTax::taxAmount (long itemSold, double price) 
    26 {
    27     // in real life, figure out tax according to
    28     // the rules in Canada and return it
    29     // here, return 0 so this will compile
    30     return 0.0;
    31 }
    USTax.h
     1 //USTax.h
     2 #pragma once
     3 #include "calctax.h"
     4 
     5 class USTax :
     6     public CalcTax
     7 {
     8 public:
     9     USTax(void);
    10     double taxAmount( long, double);
    11 
    12 public:
    13     ~USTax(void);
    14 };
    15 USTax.cpp
    16 #include "USTax.h"
    17 
    18 USTax::USTax(void)
    19 {
    20 }
    21 
    22 USTax::~USTax(void)
    23 {
    24 }
    25 
    26 double USTax::taxAmount (long itemSold, double price) 
    27 {
    28     // in real life, figure out tax according to
    29     // the rules in the US and return it
    30     // here, return 0 so this will compile
    31     return 0.0;
    32 }
  • 相关阅读:
    消息队列之kafka
    注册中心ZooKeeper
    消息队列之RocketMQ集群部署
    消息队列之RocketMQ简介及单机部署
    消息队列之RabbitMQ
    消息队列简介
    debian10入门(切换root用户,更改网卡配置,及更新apt源配置)
    实体间的关系
    MySQL数据库的基础使用命令大全
    ReletiveLayout布局的一些常用属性
  • 原文地址:https://www.cnblogs.com/sirocco/p/2956319.html
Copyright © 2011-2022 走看看