3

有没有人在 Ruby 中有一个使用命令组合的好例子?它是我在各种设计模式文献中看到的一种设计模式混合体,听起来很强大,但找不到任何有趣的用例或代码。

4

2 回答 2

3

受此博客文章中的一般思想和示例模式实现的启发,下面简要介绍一下它的外观:

class CompositeCommand
  def initialize(description, command, undo)
    @description=description; @command=command; @undo=undo
    @children = []
  end
  def add_child(child); @children << child; self; end
  def execute
    @command.call() if @command && @command.is_a?(Proc)
    @children.each {|child| child.execute}
  end
  def undo
    @children.reverse.each {|child| child.undo}
    @undo.call() if @undo && @undo.is_a?(Proc)
  end
end

以及使用软件安装程序应用程序的示例用法:

class CreateFiles < CompositeCommand
  def initialize(name)
    cmd = Proc.new { puts "OK: #{name} files created" }
    undo = Proc.new { puts "OK: #{name} files removed" }
    super("Creating #{name} Files", cmd, undo)
  end
end

class SoftwareInstaller
  def initialize; @commands=[]; end
  def add_command(cmd); @commands << cmd; self; end
  def install; @commands.each(&:execute); self; end
  def uninstall; @commands.reverse.each(&:undo); self end
end

installer = SoftwareInstaller.new
installer.add_command(
  CreateFiles.new('Binary').add_child(
    CreateFiles.new('Library')).add_child(
    CreateFiles.new('Executable')))
installer.add_command(
  CreateFiles.new('Settings').add_child(
    CreateFiles.new('Configuration')).add_child(
    CreateFiles.new('Preferences')).add_child(
    CreateFiles.new('Help')))
installer.install # => Runs all commands recursively
installer.uninstall
于 2012-05-12T20:16:50.217 回答
1

我正在尝试自己理解这种模式,并且一直在考虑可能以这种方式建模的东西。

复合模式的基本思想是在某些情况下需要以相同的方式处理项目和集合。集合可能包含项目和子集合的混合,嵌套尽可能深。

我有一些想法(从Design Patterns in RubyRuby Under a Microscope中借用一些):

文件系统

您可以询问文件的大小,它会返回一个简单的值。您还可以询问文件夹的大小,它会返回其文件和子文件夹大小的总和。子文件夹当然会返回其文件和子文件夹的总和。

同样,文件和文件夹都可以移动、重命名、删除、备份、压缩等。

一个系统命令

命令对象可以有一个run方法。该方法可以通过运行任意数量的子命令来工作,这些子命令具有子命令等。如果它的所有子命令都返回 true,它可以返回 true,并且可以根据其子命令的统计信息(经过的时间、文件修改等)报告统计信息。

公司层次结构

个人、团队、部门和整个公司都可以被视为有薪水、带来收入、完成工作单元等。

一个军事单位

在游戏中,士兵可以拥有防御和进攻统计数据,可以被告知移动到某个位置,攻击基地等。团和师可以以同样的方式对待。

重量或货币价值

装满箱子的卡车的重量包括每个箱子的重量。每个箱子的重量包括它的每个物品的重量,它们的零件等。

同样,金融投资组合的货币价值是其所有资产的价值。其中一些资产可能是包含多只股票的指数基金。您可以买卖单个股票或整个投资组合。

图形用户界面元素

一个窗口可以由框架组成,框架由框架组成,框架由框架组成。任何元素都可以定位、着色、聚焦、隐藏等。

编程语言中的表达式

当 Ruby 解释器评估一个表达式时,它通过将它分解为一个表达式树(抽象语法树)并评估每个表达式,然后通过返回树的顶部来得出最终值。从某种意义上说,树的每一层都被问到同一个问题:“你的价值是什么?”

举个简单的例子,求 的值的第一步((4 + 8) * 2)) + 9是求 的值4 + 8

于 2012-11-27T14:22:59.910 回答