リファクタリングの実例2:第4回

Advertisement

仕上げ

前回のコードを効率・安全性の面から考えてみる。

変数の再移動

前回作成したスーパークラス
public class Search implements SelectInterface{
    private String シリアルコード;
    private String 製品担当者コード;
    private String 解約月;
    private String 取消月;
    private String 返品月;

    public PreparedStatement setBind(PreparedStatement stmt){}
    public String getSql(){}

    public void execute(){
        //try{
            String sql = this.getSql();
            //Connection con = null;
            //PreparedStatement stmt = null;
            //stmt = con.prepareStatement(sql);
            //stmt = this.setBind(stmt);
            // 取得したSQLを実行
            System.out.println(sql);
        //}catch(SQLException e){
        //    e.printStackTrace();
        //}
    }
}

サブクラスSearchNormal
public class SearchNormal extends Search{
    public String getSql(){//略}
    public PreparedStatement setBind(PreparedStatement stmt){//略}

ここで各変数に注目してみると、シリアルコード・製品担当者コード以外は各サブクラスに固有の変数であることがわかる。

よって、それらのメソッドはサブクラスに移動する。

修正後スーパークラス
public class Search implements SelectInterface{
    private String シリアルコード;
    private String 製品担当者コード;

    public PreparedStatement setBind(PreparedStatement stmt){}
    public String getSql(){}

    public void execute(){
        //try{
            String sql = this.getSql();
            //Connection con = null;
            //PreparedStatement stmt = null;
            //stmt = con.prepareStatement(sql);
            //stmt = this.setBind(stmt);
            // 取得したSQLを実行
            System.out.println(sql);
        //}catch(SQLException e){
        //    e.printStackTrace();
        //}
    }
}

クラスの抽象化

現在の設計では、スーパークラスがインターフェースを実装し、サブクラスはスーパークラスのメソッドをオーバーライドするような継承関係になる(図1)
継承関係
図1:継承関係

ここには盲点があり、各サブクラスがgetSql, setBindの実装を怠ったとしても、何の問題もなくコンパイルすることが出来てしまうのである。この問題はインターフェースとクラスで階層を築いていたときにはメソッドの実装を強制できるため回避できていたが、間にスーパークラスを作成したため、新たに発生してしまった問題なのである。

  1. 各サブクラスがインタフェースを実装する
  2. スーパークラスを抽象化する
1番目の方法
各サブクラスがインタフェースを実装することでメソッドの宣言を強制できるが、スーパークラスを作成した意味がなくなる。
インタフェースの実装を忘れる可能性がある。

2番目の方法
スーパークラスの抽象化により、指定したメソッドのみ強制することができる。そもそもこのスーパークラスからはオブジェクトを生成することはなく、抽象的なものとして作成したクラスなので抽象クラスとするのが適していると考えられる。

よって、スーパークラスを抽象化する。
public abstract class Search implements SelectInterface{
    private String シリアルコード;
    private String 製品担当者コード;

    abstract public PreparedStatement setBind(PreparedStatement stmt){}
    abstract public String getSql(){}

    public void execute(){
        //try{
            String sql = this.getSql();
            //Connection con = null;
            //PreparedStatement stmt = null;
            //stmt = con.prepareStatement(sql);
            //stmt = this.setBind(stmt);
            // 取得したSQLを実行
            System.out.println(sql);
        //}catch(SQLException e){
        //    e.printStackTrace();
        //}
    }
}
以上。完成。

Advertisement

ショートカット

634トップページ
このカテゴリのトップページに戻る
634ラボ

サイト検索

Google

Web サイト内

Y!ログール