写了半天居然异常了,晕死,下面先上代码
1#include "stdafx.h"
2#include <iostream>
3#include "boost\shared_ptr.hpp"
4using namespace std;
5using namespace boost;
6
7//--武器类
8class weapon
9{
10public:
11 void virtual attack() = 0;
12};
13
14//--剑
15class sword:public weapon
16{
17public:
18 void attack()
19 {
20 cout<<"using sword to kill 10 enemy per second!"<<endl;
21 }
22};
23
24//--弓箭
25class archery:public weapon
26{
27public:
28 void attack()
29 {
30 cout<<"using archery to kill 10 enemy per second!"<<endl;
31 }
32};
33
34class general
35{
36private:
37 weapon *m_strWeapon;
38 string m_strName;
39 shared_ptr<weapon>myWeapon;
40public:
41
42
43 general(string strName)
44 :m_strName(strName)
45 {
46 myWeapon = shared_ptr<weapon>(new sword);
47 m_strWeapon = myWeapon.get();
48 }
49 void advance()
50 {
51 cout<<"gogogo!!"<<endl;
52 }
53 void setWeapon(weapon *strWeapon)
54 {
55 m_strWeapon = strWeapon;
56 }
57
58 ~general()
59 {
60
61
62 }
63
64 void performAttack()
65 {
66 m_strWeapon->attack();
67 }
68
69};
70
71int _tmain(int argc, _TCHAR* argv[])
72{
73 //生成卢布对象
74 general LvBu("luBu");
75 //前进
76 LvBu.advance();
77 //攻击
78 LvBu.performAttack();
79
80 shared_ptr<weapon>myWeapon(new archery());
81 //更换武器
82 LvBu.setWeapon(myWeapon.get());
83 //前进
84 LvBu.advance();
85 //攻击
86 LvBu.performAttack();
87
88 return 0;
89}
90
91 运行的结果
策略模式。重新看一下它的定义:定义一系列的算法,把它们一个个的封装起来,并且使它们可以相互转换。这里所说的一系列的算法封装就是通过继承把各自的实现过程封装到子类中去(我们的例子中是指archery和Sword的实现),而所说的相互转换就是我们通过设置基类指针而只向不同的子类(我们的例子上是通过SetWeapon来实现的)。
实现时需要注意的问题:
1.什么情况下用public继承(is-a),什么情况下用组合(has-a)
2.ocp设计原理(open-close principle)
3.生产对象的释放,shared_ptr的使用和原理。
下面内容摘自
http://liangfen1224.blog.163.com/blog/static/72377647200912411718194/
优先考虑使用策略模式,而不是具体继承 (Rod)
产生的原因: 属于对象的行为模式。处理多于一个算法时候,把算法和使用算法的客户端分开(把行为和环境分割开),从而方便的选择其中一个算法。
策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
假设现在要设计一个贩卖各类书籍的电子商务网站的购物车(Shopping Cat)系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的教材类图书实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣,而对非教材类的计算机图书有3%的折扣;对其余的图书没有折扣。由于有这样复杂的折扣算法,使得价格计算问题需要系统地解决。
使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类(ConcreteStrategy)中提供。由于算法和环境独立开来,算法的增减、修改都不会影响环境和客户端。当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。策略模式相当于"可插入式(Pluggable)的算法"。
程序架构:一个客户类,一个抽象策略类(接口),若干个具体策略类。由客户类决定选择那一个具体类。
定义一系列的算法,把他们一个个封装起来,并且使它们可相互替换。Strategy模式使算法可独立于使用它的客户而变化。
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:"准备一组算法,并将每一个算法封装起来,使得它们可以互换。"
策略又称做政策(Policy)模式【GOF95】。下面是一个示意性的策略模式结构图:
这个模式涉及到三个角色:
环境(Context)角色:持有一个Strategy类的引用。
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
Strategy模式以下列几条原则为基础:
1) 每个对象都是一个具有职责的个体。
2) 这些职责不同的具体实现是通过多态的使用来完成的。
3) 概念上相同的算法具有多个不同的实现,需要进行管理
通过以下步骤,开发人员可以很容易地在软件中实现策略模型:
1)对策略对象定义一个公共接口。
2)编写策略类,该类实现了上面的公共接口。
3)策略对象的类中保存一个对策略对象的引用。
4)略对象的类中,实现对策略对象的set和get方法。
例:
public interface DatabaseStrategy {
public void process();
}
public class MysqlDBStrategy implements DatabaseStrategy {
public void process() {
System.out.println("处理Mysql数据库连接");
}
}
public class OracleDBStrategy implements DatabaseStrategy {
public void process() {
System.out.println("处理Oracle数据库连接");
}
}
public class DataBaseManager {
public void process(DatabaseStrategy dbStrategy) {
dbStrategy.process();
}
}
public class StrategyClient {
public static void main(String[] args) {
DataBaseManager manager = new DataBaseManager();
MysqlDBStrategy mysql = new MysqlDBStrategy();
manager.process(mysql);
OracleDBStrategy oracle = new OracleDBStrategy();
manager.process(oracle);
}
}
何时使用何种具体策略角色
在学习策略模式时,学员常问的一个问题是:为什么不能从策略模式中看出哪一个具体策略适用于哪一种情况呢?
答案非常简单,策略模式并不负责做这个决定。换言之,应当由客户端自己决定在什么情况下使用什么具体策略角色。策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中"退休"的方便,策略模式并不决定在何时使用何种算法。
策略模式的优点和缺点
策略模式有很多优点和缺点。它的优点有:
1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复的代码。
2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
策略模式的缺点有:
1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。
其它
策略模式与很多其它的模式都有着广泛的联系。Strategy很容易和Bridge模式相混淆。虽然它们结构很相似,但它们却是为解决不同的问题而设计的。Strategy模式注重于算法的封装,而Bridge模式注重于分离抽象和实现,为一个抽象体系提供不同的实现。Bridge模式与Strategy模式都很好的体现了"Favor composite over inheritance"的观点。
我们现在来看一个场景:我在下班在回家的路上,可以有这几种选择,走路、骑车、坐车。首先,我们需要把算法抽象出来:
public interface IStrategy
{
void OnTheWay();
}
接下来,我们需要实现走路、骑车和坐车几种方式。
public class WalkStrategy : IStrategy
{
public void OnTheWay()
{
Console.WriteLine("Walk on the road");
}
}
public class RideBickStragtegy : IStrategy
{
public void OnTheWay()
{
Console.WriteLine("Ride the bicycle on the road");
}
}
public class CarStragtegy : IStrategy
{
public void OnTheWay()
{
Console.WriteLine("Drive the car on the road");
}
}
最后再用客户端代码调用封装的算法接口,实现一个走路回家的场景:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Arrive to home");
IStrategy strategy = new WalkStrategy();
strategy.OnTheWay();
Console.Read();
}
}
运行结果如下;
Arrive to home
Walk on the road
如果我们需要实现其他的方法,只需要在Context改变一下IStrategy所示例化的对象就可以。
Strategy模式的要点:
1、Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。所谓封装算法,支持算法的变化。
2、Strategy模式提供了用条件判断语句以外的另一中选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
3、Strategy模式已算法为中心,可以和Factory Method联合使用,在工厂中使用配制文件对变化的点进行动态的配置。这样就使变化放到了运行时。
4、与Template Method相比,Strategy模式的中心跟集中在方法的封装上
注:
Strategy策略模式是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.
实际整个Strategy的核心部分就是抽象类的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速.