Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

書籍 Refactoring to Patterns | Creation | Introduce Polymorphic Creation With Factory Method

パンくず

書籍 Patterns to Patterns
Creation
Introduce Polymorphic Creation With Factory Method

概要

Introduce Polymorphic Creation With Factory Methodのリファクタリングについて

使用する場面

複数のクラスを同一の型で扱うFactory Methodにしたい。
ポリモルフィズムを適用したい

対応方法

Factory Methodを導入し、ポリモルフィズムを実現する

利点と欠点

利点

・個別にオブジェクトを作成した場合に比べ、重複が減る。
・どこでオブジェクトの生成が行われ、どのようにオーバーライドされたのかわかりやすくなる
・Factoryによって実装されることで、クラスの型を強制する。

欠点

・Factoryの実装に不要なパラメータを無視できない

手順

1.似たメソッドをもつサブクラスかあり、個別にオブジェクト生成がされている処理を変更する。
この処理をInstantiation Methodと呼ぶことにする。
あなたはこのリファクタリングをExtract Methodで使う。
Methodに一般的な名前をつける。

2.ステップ1を似たようなMethodをもつサブクラス分繰り返す。

3.次にExtract SuperClassを適用する。
この兄弟クラスのスーパークラスはFactory Method:Creatorと呼ぶ。

4.Template Methodを適用する。
Pull Up Methodを使用する。
Instantiation Methodのために、スーパークラスに抽象メソッドを宣言する。
抽象メソッドを宣言したら、Factory Methodを実装する。
各兄弟サブクラスはFactory Method:ConcreteCreatorである。

5.1~4を繰り返す。

6.各Concrete Creatorに、似た処理があればスーパークラスに移動する

サンプル

リファクタリング
# encoding: Windows-31J

class JUnit
  def unit_test
    puts "execute JUnit Test"
  end
end

class RSpec
  def unit_test
    puts "execute RSpec"
  end
end

class Java
  def unit_test()
    puts "coding"
    unit_tester = JUnit.new
    unit_tester.unit_test
  end
end

class Ruby
  def unit_test()
    puts "coding"
    unit_tester = RSpec.new
    unit_tester.unit_test
  end
end

[Java.new, Ruby.new].each {|language|
  language.unit_test
}
リファクタリング
# encoding: Windows-31J

class JUnit
  def unit_test
    puts "execute JUnit Test"
  end
end

class RSpec
  def unit_test
    puts "execute RSpec"
  end
end

class ProgramLanguage
  def get_unit_test
    get_unit_test
  end
  
  def unit_test()
    puts "coding"
    unit_tester = get_unit_test
    unit_tester.unit_test
  end
end

class Java < ProgramLanguage
  def get_unit_test
    JUnit.new
  end
end

class Ruby < ProgramLanguage
  def get_unit_test
    RSpec.new
  end
end

[Java.new, Ruby.new].each {|language|
  language.unit_test
}