web-dev-qa-db-ja.com

継承と工場は一緒ですか?

階層データモデルがあり、自分のWebアプリケーションにそれらのCRUD操作を実装しようとしています。

現在、次のようにエンティティ(リソース)のCRUD操作のコード継承があります。

基本クラスとしてのResourceCommonProcedures、および基本クラスを継承する各Resourceプロシージャ。

_public class ResourceCommonProcedures { 

    public Response create(Request request){
        Response response = new Response();
        int resType = this.getResourceType(request);

        ResourceCommonProcedures rp = getResourceController(resType);
        response = rp.create(request);

        return response;
    }

private ResourceCommonProcedures getResourceController(int resourceType){
            //..

            switch(resourceTypeName){


            case Resource1:
                return new R1Procedures();

            case Resource2:
                return new R2Procedures();

            case Resource3:
                return new R3Procedures();
            ............... 

}
}

Class R1Procedures extends ResourceCommonProcedures{


public Response create(Request request) {

        Response response = new Response();
            Resource1 resource = (Resource1) request.getContent();

            ...........
            // Converts DB structure to JPA 
            R1Converter r1Converter = new R1Converter();
            Resource1JPA resourceJpa = r1Converter.toJPA(resource);
            dao.persist();

            return response;

}
}

Class R2Procedures extends ResourceCommonProcedures{


public Response create(Request request) {

        Response response = new Response();
            Resource1 resource = (Resource2) request.getContent();

            // SOME RESOURCE 2 SPECIFIC CODE
            ...........
            // Converts DB structure to JPA 
            R2Converter r2Converter = new R2Converter();
            Resource2JPA resourceJpa = r2Converter.toJPA(resource);
            dao.persist();

            return response;


}
_

したがって、現在、ベースには、呼び出す必要があるサブクラスメソッドを決定するコントローラーコードがあります。

したがって、クライアントは基本クラスのcreateメソッドを呼び出します。このメソッドは内部で実装クラスを取得し、特定のcreateメソッドを呼び出します。

このデザインは十分ですか?

または、getResourceController()を基本クラスから取り出して別のクラスに配置する必要がありますか?

ケース特有のデザインパターンはありますか?

4

私は抽象ジェネリッククラスに行きます:

public class AbstractProcedure<T extends BusinessObject, TJPA extends JPAObject, TConverter extends Converter<T, TJPA >>{

public abstract TConverter<T, TJPA> getConverter();

public Response create(Request request) {
    Response response = new Response();
        T resource = (T) request.getContent();

        ...........
        // Converts DB structure to JPA 
        R1Converter r1Converter = getConverter();
        TJPA resourceJpa = r1Converter.toJPA(resource);
        dao.persist(resourceJpa);
        return response;
    }
 }

public class R1Converter implements Converter<R1, R1JPA>{
         @Override // come from the Converter interface
         public R1JPA toJpa(R1 object){}
}
public class R1Procedure extends AbstractProcedure<R1, R1JPA, R1Converter>{
      R1Converter converter = new R1Converter();
      public R1Converter getConverter(){
           return converter;
      }
}

考慮すべき点:

  • 「コンバーター」の名前を「アダプター」に変更することをお勧めします
  • リクエストからデータを取得するのと同じクラスでデータベースリクエストを処理することは、通常、問題を分離するためにクラスを分離します。明日、バッチでエンティティを作成する必要がある場合はどうなりますか?
  • Create関数をオーバーライドしてデフォルト値を追加し、右チェックしてsuper.create()を呼び出すことができます。 superの使用は推奨されませんが、これはIMHOの常識的な使用法です。
2
Walfrat

これは少し変わったデザインです。継承のポイントは、これらの大きなifブロックが必要ないようにすることです。

共通のgetResourceControllerを仮想化すると、子クラスでそれをオーバーライドし、そこにクラス固有のロジックを実装できます。スイッチケースを節約できます。

すなわち。 getResourceController(int resourceType)は継承されます(そして呼び出されますか?)R1Procedures。 resourceTypeはクラスインスタンスに格納されます

int resType = this.getResourceType(request);

そのため、getResourceControllerロジックの独自のブランチを呼び出すだけでよい、インスタンス化されたR1Proceduresがすでにあるはずです。

しかし、おそらくこれをさらに進めて、低音クラスを完全に削除することができます。サンプルコードに共通の機能はありません。

コード例に欠けているのは、タイプXのクラスを作成する必要がある初期入力です。これは、ロジックで使用するさまざまなオブジェクトをインスタンス化する方法を決定する重要な要素であるこのエントリポイントです。

2
Ewan