设计模式(三)Strategy,Chain of Responsibility

本文介绍了策略模式和职责链模式的基本概念及实现方式。策略模式允许在运行时选择算法,通过组合而非继承来实现代码的灵活性。职责链模式则尝试采用一系列策略模式,直至找到解决问题的有效方法。
Strategy:运行时选择算法。

注意,模板方法模式是“坚持相同的代码”,而被覆盖的函数是“变化的代码”。然而,这种变化在编译时通过继承被固定下来。按照“组合优于继承”的格方,可以利用组合来解决将变化的代码从“坚持相同的代码”中分开的问题,从而产生策略(Strategy)模式。这种方法有一个明显的好处:在程序运行时,可以插入变化的代码。策略模式也加入了“语境”,它可以是一个代理类,这个类控制着对特定策略对象的选择和使用--就像状态模式一样。

“策略”的意思就是:可以使用多种方法来解决某个问题--即“条条大路通罗马”。现在考虑一下忘记了某个人姓名时的情景。这里的程序可以用不同方法解决这个问题。

//: C10:Strategy.cpp
// The Strategy design pattern.
#include <iostream>
using namespace std;
 
class NameStrategy {
public:
  virtual void greet() = 0;
};
 
class SayHi : public NameStrategy {
public:
  void greet() {
    cout << "Hi! How's it going?" << endl;
  }
};
 
class Ignore : public NameStrategy {
public:
  void greet() {
    cout << "(Pretend I don't see you)" << endl;
  }
};
 
class Admission : public NameStrategy {
public:
  void greet() {
    cout << "I'm sorry. I forgot your name." << endl;
  }
};
 
// The "Context" controls the strategy:
class Context {
  NameStrategy& strategy;
public:
  Context(NameStrategy& strat) : strategy(strat) {}
  void greet() { strategy.greet(); }
};
 
int main() {
  SayHi sayhi;
  Ignore ignore;
  Admission admission;
  Context c1(sayhi), c2(ignore), c3(admission);
  c1.greet();
  c2.greet();
  c3.greet();
} ///:~
 
<style type="text/css"> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }</style>

Context::greet()可以正规地写得更复杂些,它类似模板方法模式,因为其中包含了不能改变的代码。但在函数main()中可以看到,可以在运行时就策略进行选择。更进一步的做法,可以将状态模式与在Context对象的生存期期间的变化的策略模式结合起来使用。

Chain of Responsibility:尝试采用一系列策略模式。

职责链模式也许被看做一个使用策略对象的“递归的动态一般化”。此时提出一个调用,在一个链序列中的每个策略都试图满足这个调用。这个过程直到有一个策略成功满足该调用或者到达链序列的末尾才结束。在递归方法中,有个函数反复调用其自身直至达到某个终止条件。

//: C10:ChainOfReponsibility.cpp
// The approach of the five-year-old.
#include <iostream>
#include <vector>
#include "../purge.h"
using namespace std;


  
enum Answer { NO, YES };


  
class GimmeStrategy {
public:
    virtual Answer canIHave() = 0;
    virtual ~GimmeStrategy() {}
};


  
class AskMom : public GimmeStrategy {
public:
    Answer canIHave() {
        cout << "Mooom? Can I have this?" << endl;
        return NO;
    }
};


  
class AskDad : public GimmeStrategy {
public:
    Answer canIHave() {
        cout << "Dad, I really need this!" << endl;
        return NO;
    }
};


  
class AskGrandpa : public GimmeStrategy {
public:
    Answer canIHave() {
        cout << "Grandpa, is it my birthday yet?" << endl;
        return NO;
    }
};


  
class AskGrandma : public GimmeStrategy {
public:
    Answer canIHave() {
        cout << "Grandma, I really love you!" << endl;
        return YES;
    }
};


  
class Gimme : public GimmeStrategy {
    vector<GimmeStrategy*> chain;
public:
    Gimme() {
        chain.push_back(new AskMom());
        chain.push_back(new AskDad());
        chain.push_back(new AskGrandpa());
        chain.push_back(new AskGrandma());
    }
    Answer canIHave() {
        vector<GimmeStrategy*>::iterator it = chain.begin();
        while(it != chain.end())
            if((*it++)->canIHave() == YES)
                return YES;
        // Reached end without success...
        cout << "Whiiiiinnne!" << endl;
        return NO;
    }
    ~Gimme() { purge(chain); }
};


  
int main() {
    Gimme chain;
    chain.canIHave();
} ///:~
职责链的本质是尝试多个解决方法直到找到一个起作用的方法。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值