论坛首页 编程语言技术论坛

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

浏览 1651 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-11   最后修改:2010-01-13
策略模式还有个别名叫政策模式(Policy),属对象行为型模式。


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

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

不合适的地方有:
  • 代码乱
  • 多余的引用
  • 修改困难
  • 不好测试



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


结构:



在动态语言里边(如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 等。

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


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


看了上面的介绍大家可能会觉得策略模式跟前面讲到的模板方法没什么区别,不就都是将算法封装吗?下面讲下他们的区别:

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


下面是一个例子:

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)


源码文件点击下载

类图:


  • 大小: 95.2 KB
  • 大小: 17.4 KB
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics