设计模式与动态语言 之 策略模式(strategy)

策略模式还有个别名叫政策模式(Policy),属对象行为型模式。


意图:[b]定义一系列算法,把它们一个个封闭起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化[/b]

动机:把算法硬编写在使用他们的类中是不合适的。

不合适的地方有:
[list]
[*]代码乱
[*]多余的引用
[*]修改困难
[*]不好测试
[/list]


适用性:
[list]
[*]许多相关的类仅仅是行为不同
[*]需要使用一个算法的不同变体
[*]一个类定义了多种行为,并且这些行为在操作用以多个条件语句的形式出现。
[/list]

结构:

[img]http://dl.iteye.com/upload/attachment/166526/0e1da56d-1953-32c6-a2e7-0df728287ded.png[/img]

在动态语言里边(如Ruby),可以没有父类,用Proc和代码块可以简单实现策略模式

如:
hello = lambda {
puts "I am a proc"
}

hello.call


def run_it
puts "before"
yield
puts "after"
end

run_it do
puts "I am a yield"
end


在Ruby中还有很多轻量级策略对象,像 sort map select each 等。

效果:
[list]
[*]使算法或行为可重用
[*]继承有助于取出这些算法的公共功能
[*]算法实现与Context分离,易切换,理解,扩展
[*]算法委托给父类,省去部分Case
[*]方便单元测试
[/list]

用该模式应注意:
[list]
[*]环境对象和策略对象的接口弄错。将完整一致的,可独立的工作移出环境对象, 然后用策略对象来代理它。
[*]注意,如果你将你的环境对象和某一个策略对象过紧耦合,而无法设计中推出第二个和第三个策略对象, 那就是误用
[*]切换时必须了解不同的Strategy
[/list]

看了上面的介绍大家可能会觉得策略模式跟前面讲到的[url=http://jim-jin.iteye.com/blog/508295]模板方法[/url]没什么区别,不就都是将算法封装吗?下面讲下他们的区别:

[list]
[*]策略模式用组合,模版模式用继承,说白了就是一个封装一组算法(多算法),一个封装一个算法(单算法)。
[*]模版模式就是算法在父类中,子类不会完全改写算法,可以改写部分,或称关键部分,但整体的算法不变,可以节省大量代码
[*]策略侧重不同的行为的改变在统一的接口下,强调多态下面行为的执行过程,处理过程,可以从用户那里接受参数,只要用户提供的策略符合接口
[*]策略模式所有的算法均在子类中完成,强调行为即算法的不同,可以使程序更灵活,而模版模式中子类不能改变父类算法结构.
[/list]

下面是一个例子:


class Hero
def kill(bug, skill)
skill.do(bug)
end
end

# 技能
class Skill
def do(bug="bug")
raise "This is abstract method"
end
end

# 雷电
class Thunder < Skill
def do(bug="bug")
puts '延迟3秒'
puts '闪电2下'
puts '连续的打雷'
puts "#{bug} 减血1000"
end
end

# 地震
class Earthquake < Skill
def do(bug)
puts "#{bug} 减血500"
puts '连续的地震波2秒'
puts "#{bug} 眩晕5秒"
end
end

# 旋风
class Whirlwind < Skill
def do(bug)
puts '范围100 旋风5秒并移动'
puts "#{bug} 连续减血150/每秒 "
end
end

puts "\r\n"
puts '打猪'
puts "------------"
Hero.new.kill('小猪', Thunder.new)

puts "\r\n"
puts '打小白'
puts "------------"
Hero.new.kill('小白', Earthquake.new)

puts "\r\n"
puts '打牛'
puts "------------"
Hero.new.kill('大牛', Whirlwind.new)


[url=http://dl.iteye.com/topics/download/c9d59dc3-0123-35ef-8992-85012739607a]源码文件点击下载[/url]

类图:

[img]http://dl.iteye.com/upload/attachment/166619/5be08893-aeb6-37a1-aaef-c4ddbc3e2f84.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
策略模式Strategy Pattern)是一种行为型设计模式,它定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的客户端。其实就是将一系列的算法封装起来,从而使它们可以相互替换。 使用C++实现策略模式可以按照以下步骤: 1. 定义一个策略接口类,该类定义了所有策略类都必须实现的方法。 ```c++ class Strategy { public: virtual void execute() = 0; virtual ~Strategy() {} }; ``` 2. 实现多个具体的策略类,这些类实现了策略接口中定义的方法,进行不同的算法处理。 ```c++ class ConcreteStrategyA : public Strategy { public: void execute() override { cout << "Executing strategy A" << endl; } }; class ConcreteStrategyB : public Strategy { public: void execute() override { cout << "Executing strategy B" << endl; } }; class ConcreteStrategyC : public Strategy { public: void execute() override { cout << "Executing strategy C" << endl; } }; ``` 3. 定义一个环境类,该类持有一个策略对象,并且在运行时可以根据需要更改策略对象。 ```c++ class Context { private: Strategy* strategy_; public: Context(Strategy* strategy = nullptr) : strategy_(strategy) {} void set_strategy(Strategy* strategy) { strategy_ = strategy; } void execute_strategy() { if (strategy_) { strategy_->execute(); } } ~Context() { delete strategy_; } }; ``` 4. 在客户端中,创建不同的策略对象,并且将它们传递给环境对象,从而触发不同的算法处理。 ```c++ int main() { Strategy* strategyA = new ConcreteStrategyA(); Strategy* strategyB = new ConcreteStrategyB(); Strategy* strategyC = new ConcreteStrategyC(); Context context1(strategyA); context1.execute_strategy(); context1.set_strategy(strategyB); context1.execute_strategy(); context1.set_strategy(strategyC); context1.execute_strategy(); Context context2(strategyB); context2.execute_strategy(); context2.set_strategy(strategyC); context2.execute_strategy(); delete strategyA; delete strategyB; delete strategyC; return 0; } ``` 以上代码实现了一个简单的策略模式。在该模式中,我们定义了三个具体的策略类:ConcreteStrategyA,ConcreteStrategyB和ConcreteStrategyC。我们还定义了一个Context类,该类持有一个策略对象,并且在运行时可以更改策略对象。在客户端中,我们创建了不同的策略对象,并且将它们传递给不同的Context对象,从而触发不同的算法处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值