2017-06-07 13 views
0

2つのパターン(テンプレートと戦略)は類似しているようです。テンプレートメソッドには、変更する必要がある処理を駆動する骨格メソッドを持つ抽象基本クラスがあります。この処理は、具象クラスによって提供される抽象メソッドを呼び出すことによって行われます。具体的なクラスを選ぶことで、私たちが望むバリエーションを選択します。テンプレートパターンと戦略パターンの違いは何ですか?

たとえば、私たちはReportクラスを持ち、HTMLReportクラスはReportから継承しています。私たちのReportクラスは次のようになります。

class Report 
def initialize 
@title = 'Monthly Report' 
@text = ['Things are going', 'really really well'] 
end 

def output_report 
output_start 
output_head 
output_body_start 
output_body 
output_body_end 
output_end 
end 


def output_body 
@text.each do |line| 
output_line(line) 
end 

def output_start 
raise StandardError 
end 

def output_head 
raise 'This needs to be implemented by the concrete class' 
end 
... 
end 

と私たちの実際の具体的なクラス:

class HTMLReport < Report 
def output_start 
puts('<html>') 
end 

def output_head 
puts(' <head>') 
... 
end 

... 
end 

実際の使用を:

report = HTMLReport.new 
report.output_report 

重要なのは、抽象クラスがために他のメソッドを呼び出すことですアルゴリズムの変数部分を継承することができます(この場合はRubyの継承を介して継承することができます)。次に実際の実装を行います。

しかし、いくつかの欠点(Russ Olsenによる): - 継承を使用します。実行時の柔軟性を制限します...特定のバージョンのalgoを選択すると、私たちの心を変えるのは難しいです。

したがって、戦略パターン: - 厄介な様々なコードを取り出し、それを独自のクラスで分離します。次に、バリエーションごとに1つのクラスのファミリを作成します。

例:

class Formatter 
def output_report(title, text) 
raise 'Abstract Method called' 
end 
end 

class HTMLFormatter < Formatter 
def output_report(title, text) 
puts('<html>') 
puts(' <head>') 
puts(" <title>#{title}</title>") 
puts(' </head>') 
... 
end 

今すぐ私たちのReportクラスは次のようになります。

class Report 
attr_reader :title, :text 
attr_accessor :formatter 

def initialize(formatter) 
@title = 'Monthly Report' 
@text = ['Things are going', 'really, really well.'] 
@formatter = formatter 
end 

def output_report 
@formatter.output_report(@title, @text) 
end 
end 

だから、私が間違っている場合、それは同じインタフェースを持っているすべての戦略以来のように見える私を修正し、我々はReportクラスでそれらに委託することができます。 Reportクラスは、GOFの人々によってcontextと呼ばれています。

しかし、これによって実行時に戦略をどのように切り替えることができますか?私たちはまだそれをこのように呼びますか?

report = Report.new(HTMLFormatter.new) 
report.output_report 

主な違いは何ですか?

+0

テンプレートメソッドバージョンで書式を変更する場合は、別のサブクラスが必要なため、完全に新しいレポートを作成する必要があります。戦略バージョンでは、新しいフォーマッタを既存のレポートに割り当てることができます。 –

答えて

1

テンプレートパターンはあまりパターンではありません。多形の基本であることがわかっているだけです。一方、戦略パターンは、実行時にスワップアウトできる「関数」/「戦略」の共通インタフェースを定義します。 Javaの戦略パターンの例を以下に示します(申し訳ありませんが、Rubyには詳しくない)。

public interface Strategy { 
    public int doOperation(int num1, int num2); 
} 

public class OperationAdd implements Strategy{ 
    @Override 
    public int doOperation(int num1, int num2) { 
    return num1 + num2; 
    } 
} 

public class OperationSubstract implements Strategy{ 
    @Override 
    public int doOperation(int num1, int num2) { 
     return num1 - num2; 
    } 
} 

// Using this Context and common Strategy interface, we can utilize any operation 
// we want. 
public class Context { 
    private Strategy strategy; 

    public Context(Strategy strategy){ 
     this.strategy = strategy; 
    } 

    public int executeStrategy(int num1, int num2){ 
     return strategy.doOperation(num1, num2); 
    } 
} 

public class StrategyPatternDemo { 

    public static void main(String[] args) { 

     // Implement any Operation that implements Strategy interface 
     Context context = new Context(new OperationAdd());  
     System.out.println("10 + 5 = " + context.executeStrategy(10, 5)); 

     context = new Context(new OperationSubstract());  
     System.out.println("10 - 5 = " + context.executeStrategy(10, 5)); 

     context = new Context(new OperationMultiply());  
     System.out.println("10 * 5 = " + context.executeStrategy(10, 5)); 
    } 
} 
+0

ImはJavaに精通していません。 – Jwan622

+0

確かに、私は今週Rubyを学び始めたので、Rubyでこれを行う方法はあまりよく分かりませんが、それができると確信しています。 Create Classes "Strategy"という基底クラスから継承した "Add"、 "Subtract"を呼び出し、doOperationというメソッドでその作業を行います。 'execute'メソッドを使って" Context "と呼ばれる別のクラスを作成します。この 'execute'メソッドの中で、" Context "はこの' doOperation'メソッドを呼び出します。 Contextが作成されると、それは実行されるべきOperationの型で作成されます。これはex: 'Context.new(新規追加)' - それが有効なRubyでもある場合です。 – jiveturkey

+0

または、あなたのJavaを介して私に話すことを意味しますか?私は錆びています...これはもう何ですか? 'main(String [] args)'と 'private Strategy strategy'と' public int doOperation(int num1、int num2){ return num1 - num2; } '? – Jwan622

関連する問題