Home > IT > Java言語で学ぶリファクタリング入門 #8, #11

Java言語で学ぶリファクタリング入門 #8, #11

  • 2009-02-05 (Thu)
  • IT

前回の続き。
・・・ですが、このエントリーは去年から下書きで放置されていたぽ。

 Mysidian mysidian = new WarlockReport(); //TODO パラメータに応じたインスタンスを生成する
 ShunmiFactor factor = mysidian.getShunmiFactor();

結論からいうと switch 文は消えません。
・・・とするつもりだったのですが、無理やり消してみました。
最終的にはこうなります。

 Mysidian mysidian = MysidiaFactory.createMysidian(1);
 ShunmiFactor factor = mysidian.getShunmiFactor();

createMysidian に渡している引数がマジックナンバーに見えますが、これは変数だと思ってください。
ブラウザのフォームで入力された 1 という値、あるいは Oracle(データベースの)から SELECT された値などに相当します。
2 でも 3 でも構いません。

今回のリファクタリングでは以下のコードを書き換えました。

public abstract class Mysidian にメソッド newInstance を追加
public enum MysidianProperties を追加
public class MysidiaFactory を追加
public class MysidianCreateException を追加

順に見ていきます。

まず、Mysidian の newInstance。

 Mysidian newInstance(){
  Mysidian instance = null;
  try {
   instance =  this.getClass().newInstance();
  } catch (InstantiationException e) {
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
  }
  return instance;
 }

単純に自分の新たなインスタンスを返します。
Mysidian は抽象クラスなので、実際はサブクラスの各インスタンスが返ります。

次に MysidianProperties。
名前はさておき、コードは前々回の enum Mysidian を少し書き換えたものです。

public enum MysidianProperties {
 WARLOCKREPORT(new WarlockReport(),1),
 DIEL(new Diel(),2),
 ELIO(new Elio(),3);
 private final Mysidian mysidian;
 private final int typeCode;
 private MysidianProperties(Mysidian mysidian, int typeCode){
  this.mysidian = mysidian;
  this.typeCode = typeCode;
 }
 public Mysidian getMysidian(){
  return this.mysidian;
 }
 public int getTypeCode() {
  return typeCode;
 }
}

private コンストラクタが引数に Mysidian とそれに対応した typeCode を取るようになっています。

そして MysidiaFactory。
これは少しずつ見てきましょう。
まず static イニシャライザ。

 private static final Map MYSIDIAN_MAP = new HashMap();
 static{
  for(MysidianProperties value : MysidianProperties.values()){
   MYSIDIAN_MAP.put(value.getTypeCode(), value.getMysidian());
  }
 }

ここでは MYSIDIAN_MAP に MysidianProperties の typeCode を key、mysidian を value として put していきます。

次に createMysidian メソッド。

 public static Mysidian createMysidian(int typeCode) throws MysidianCreateException{
  Mysidian misidian = MYSIDIAN_MAP.get(typeCode);
  if(misidian == null){
   throw new MysidianCreateException();
  }
  return misidian.newInstance();
 } 

まず、引数として受け取った typeCode を key に MYSIDIAN_MAP から mysidian の取得を試みます。
null の場合(引数の値が 1、 2、 3 以外の場合)は MysidianCreateException を throw します。
mysidian が取得できたら、newInstance メソッドで新たなインスタンスを生成して返します。

・・・ということで、最初のコード

 Mysidian mysidian = MysidiaFactory.createMysidian(1);
 ShunmiFactor factor = mysidian.getShunmiFactor();

のようになり、createMysidian に 1 が渡った場合は、WarlockReport、2 の場合は Diel、3 の場合は Elio として処理が進みます。
MysidiaFactory の private な Map に各 Mysidian インスタンスを持たせるところは検討の余地がありますが、ひとまず switch 文は消えました。
この辺つっこんでもらえれば(誰かに)。

Java言語で学ぶリファクタリング入門

次回はこれまでのリファクタリングによるメリットとデメリットについて考えてみたいと思います。

Home > IT > Java言語で学ぶリファクタリング入門 #8, #11

Page Top