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

私はこのパターンを自分で理解しようとしており、このようにモデル化される可能性のあるものについて熟考しています。

複合パターンの基本的な考え方は、アイテムとコレクションをいくつかの点で同じように扱う必要がある状況です。コレクションには、アイテムとサブコレクションが混在している場合があり、必要なだけ深くネストされています。

私が持っているいくつかのアイデア(RubyとRuby Under a Microscopeのデザインパターンからいくつかを借りています):

ファイルシステム

ファイルにサイズを尋ねると、単純な値が返されます。フォルダにサイズを尋ねることもでき、ファイルとサブフォルダのサイズの合計を返します。もちろん、サブフォルダーはファイルとサブフォルダーの合計を返します。

同様に、ファイルとフォルダの両方を移動、名前変更、削除、バックアップ、圧縮などすることができます。

システムコマンド

コマンドオブジェクトはrunメソッドを持つことができます。このメソッドは、サブコマンドなどを含む任意の数のサブコマンドを実行することで機能します。すべてのサブコマンドがtrueを返す場合はtrueを返し、子の統計(経過時間、変更されたファイルなど)に基づいて統計を報告できます。

会社の階層

個人、チーム、部門、および会社全体はすべて、給与を持っている、収入をもたらしている、作業単位を完了しているなどと見なされる可能性があります。

軍隊

ゲームでは、兵士は防御と攻撃の統計を持ち、場所に移動したり、基地を攻撃したりするように指示される可能性があります。連隊と師団は同じように扱われる可能性があります。

重量または金銭的価値

ボックスでいっぱいのトラックの重量には、各ボックスの重量が含まれます。各箱の重量には、各アイテムの重量、部品などが含まれます。

同様に、金融ポートフォリオの金銭的価値は、そのすべての資産の価値です。それらの資産のいくつかは、複数の株式を含むインデックスファンドである可能性があります。個別の株式またはポートフォリオ全体を売買できます。

GUI要素

ウィンドウは、フレームで構成されているフレームで構成されているフレームで構成されている可能性があります。任意の要素を配置、シェーディング、フォーカス、非表示などにすることができます。

プログラミング言語での表現

Rubyインタープリターが式を評価するときは、式のツリー(抽象構文木)に分解し、それぞれを評価して、ツリーの先頭に戻ることで最終的な値に到達します。ある意味で、ツリーの各レベルには同じ質問があります。「あなたの価値は何ですか?」

簡単な例として、の値を見つける最初のステップは、の値((4 + 8) * 2)) + 9を見つけることです4 + 8

于 2012-11-27T14:22:59.910 に答える