2017-08-03 9 views
-1

私のアプリケーションでは、実行時にいくつかの「リレーショナル」データにアクセスする必要があります。私がたくさんのデータを持っていたり、それが頻繁に変更されたら、DB(sqliteなど)に保存します。しかし、私は変更しない(しばしば)5〜50個のオブジェクトを持つエンティティを2つしか持たず、開発者だけで変更されるでしょう。ですから、単純なコードのメンテナンスのために、Javaクラスのデータを単純にハードコーディングするのは理にかなっていると思います。基本クラスを使用して静的なリレーショナルデータをハードコードする方法は?

すべてのエンティティは、共通の抽象スーパークラス(int idおよびString name)を共有します。 データを定義した後、私は各エンティティオブジェクトへの参照を持ち、Collection/Arrayにこれらのオブジェクトのすべてをクラス外で利用できるようにしたいと思います。 データが不変であることを確認したい。

最初のアイデアは、このような何かになった:

public abstract class AbstractEntity{ 

    private final int id; 
    private String name; 

    protected AbstractEntity(int id, String name){ 
     this.id = id; 
     this.name = name; 
    } 

    private void someMethods(){ 
     ... 
    } 

    abstract protected void someAbstractMethods(){ 
     ... 
    } 
} 

public final class MyEntity extends AbstractEntity{ 

    public static final ENTITY_1 = new MyEntity(1, "Entity 1", "foo"); 
    public static final ENTITY_2 = new MyEntity(2, "Entity 2", "bar"); 
    public static final ENTITY_3 = new MyEntity(3, "Entity 3", "baz"); 

    public static final Set<MyEntity> ALL = Collections.unmodifiableSet(new TreeSet<>(Arrays.asList(ENTITY_1, ENTITY_2, ENTITY_3))); 

    private final String foo; 

    private MyEntity(int id, String name, String foo){ 
     super(id, name); 
     this.foo = foo; 
    } 
} 

を私は見欠陥が開発中の新しいエンティティを追加するとき、私は同様にすべての設定に追加する必要があるということです。それは私を悩ます。冗長性とバグの原因です。

私はentitiyオブジェクトを定義し、values()配列内のオブジェクト参照の暗示的な意味を持つエンティティクラスとしてenumを使用することを考えました。 しかし、Javaでは基本クラス(AbstractEntity)と複数の継承ができないため、これは機能しません。

抽象基本クラスの代わりに、デフォルトのメソッドでインターフェイスを使用し、エンティティとしてこのインターフェイスを実装する列挙型を定義するという次のアイデアです。 しかし、基本クラス(インタフェース)にint idとString nameを定義することはできず、各サブクラスで定義する必要があります。

構文的な砂糖がありますか? ここでベストプラクティスは何ですか?

+1

これはまったく簡単ではありません。私はより良いアイデアは、データベースにそれらを保持し、最も頻繁に使用されるそれらのオブジェクトのためにメモリ内のキャッシュソリューションを提供することだと思います。 – duffymo

+2

一部の限られたデータセットでdbソリューションを使用したくない場合は、代わりにプロパティファイルを使用します。このアプローチは、データベースを模倣するために多くの不必要な作業のように思えます。 – andrewdleach

+1

エンティティをまったく作成しないでください。 ENUMを作成し、必要なフィールドを列挙型に追加し、実体に関係を格納するために列挙型を使用します。 – StanislavL

答えて

1

コメントで説明したように、むしろEnumを使用して各エンティティのインスタンスを格納します。エンティティコンストラクタにパラメータを追加して、エンティティ値をインスタンス化して格納できるようにします。

次は、私はあなたのSetは、すべてのインスタンスを格納するために維持するソリューションを提供するタイプAのentitesためEnumとタイプBのエンティティのための別の1(両方ともALLセットで使用されてAbstractEntityから継承)と。 ALLセットは、ENUMSから値を取得する静的な部分に格納されているため、新しい値を追加するために列挙型にエントリを追加する必要があります。

Entities.java

public class Entities { 

    // Entities of class A 
    private enum EntitiesOfA { 
     ENTITY_A_1(1, "EntityA 1", "foo"), // A1 
     ENTITY_A_2(2, "EntityA 2", "bar"), // A2 
     ENTITY_A_3(3, "EntityA 3", "baz"); // A3 

     private MyEntityA entity; 


     private EntitiesOfA(int id, String name, String foo) { 
      this.entity = new MyEntityA(id, name, foo); 
     } 

     public MyEntityA getEntity() { 
      return this.entity; 
     } 
    } 

    // Entities of class B 
    private enum EntitiesOfB { 
     ENTITY_B_1(4, "EntityB 1", 10), // B1 
     ENTITY_B_2(5, "EntityB 2", 11), // B2 
     ENTITY_B_3(6, "EntityB 3", 12); // B3 

     private MyEntityB entity; 


     private EntitiesOfB(int id, String name, int value) { 
      this.entity = new MyEntityB(id, name, value); 
     } 

     public MyEntityB getEntity() { 
      return this.entity; 
     } 
    } 


    // All Entities 
    public static final Set<AbstractEntity> ALL; 

    static { 
     // I use HashSet instead of TreeSet because I have 
     // not implemented the comparable interface 
     Set<AbstractEntity> allEntities = new HashSet<>(); 
     for (EntitiesOfA entity : EntitiesOfA.values()) { 
      allEntities.add(entity.getEntity()); 
     } 
     for (EntitiesOfB entity : EntitiesOfB.values()) { 
      allEntities.add(entity.getEntity()); 
     } 

     ALL = Collections.unmodifiableSet(allEntities); 
    } 


    public static void main(String[] args) { 
     for (AbstractEntity entity : ALL) { 
      System.out.println("Entity ID = " + entity.getId() + " NAME = " + entity.getName()); 
      entity.someAbstractMethods(); 

      if (entity instanceof MyEntityA) { 
       MyEntityA a = (MyEntityA) entity; 
       System.out.println("Entity A with foo = " + a.getFoo()); 
       a.someMethods(); 
      } else if (entity instanceof MyEntityB) { 
       MyEntityB b = (MyEntityB) entity; 
       System.out.println("Entity B with value = " + b.getValue()); 
       b.someMethods(); 
      } else { 
       System.err.println("ERROR: Unrecognised subclass"); 
      } 
     } 
    } 
} 

AbstractEntity.java

public abstract class AbstractEntity { 

    private final int id; 
    private String name; 


    protected AbstractEntity(int id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public int getId() { 
     return this.id; 
    } 

    public String getName() { 
     return this.name; 
    } 

    public void someMethods() { 
     // A 
    } 

    protected abstract void someAbstractMethods(); 

} 

MyEntityA。:Javaの パブリック最終クラスMyEntityAはAbstractEntity {

private final String foo; 


public MyEntityA(int id, String name, String foo) { 
    super(id, name); 

    this.foo = foo; 
} 

public String getFoo() { 
    return this.foo; 
} 

@Override 
protected void someAbstractMethods() { 
    // Some code 
} 

}

MyEntityB.java パブリック最終クラスMyEntityBがAbstractEntity {

private final int value; 


public MyEntityB(int id, String name, int value) { 
    super(id, name); 

    this.value = value; 
} 

public int getValue() { 
    return this.value; 
} 

@Override 
protected void someAbstractMethods() { 
    // Some code 
} 

}

注意それを拡張して延び

  • ENUMのコンストラクタは、必要に応じてVAL(new MyEntityA(...))に置き換えることができます。この場合、EntitesOfAEntitesOfBをマージしてすべてのエンティティを作成し、AbstractEntityのコンストラクタを使用することができます。 Setも削除できます。

    public class AllEntities { 
    
    private enum Entities { 
        ENTITY_A_1(new MyEntityA(1, "EntityA 1", "foo")), // A1 
        ENTITY_A_2(new MyEntityA(2, "EntityA 2", "bar")), // A2 
        ENTITY_A_3(new MyEntityA(3, "EntityA 3", "baz")), // A3 
        ENTITY_B_1(new MyEntityB(4, "EntityB 1", 10)), // B1 
        ENTITY_B_2(new MyEntityB(5, "EntityB 2", 11)), // B2 
        ENTITY_B_3(new MyEntityB(6, "EntityB 3", 12)); // B3 
    
        private AbstractEntity entity; 
    
    
        private Entities(AbstractEntity entity) { 
         this.entity = entity; 
        } 
    
        public AbstractEntity getEntity() { 
         return this.entity; 
        } 
    } 
    
    
    // All Entities 
    public static final Set<AbstractEntity> ALL; 
    
    static { 
        // I use HashSet instead of TreeSet because I have 
        // not implemented the comparable interface 
        Set<AbstractEntity> allEntities = new HashSet<>(); 
        for (Entities entity : Entities.values()) { 
         allEntities.add(entity.getEntity()); 
        } 
        ALL = Collections.unmodifiableSet(allEntities); 
    } 
    
  • 私はテストの主な方法を追加しましたが、削除することもできます。

+0

ありがとうございました。 エンティティをエンティティにネストするのはすばらしいトリックです。 MyEntityクラスを列挙型の静的クラスとして定義して、ソリューションを修正しました。このようにして、私はコンストラクタをプライベートに保つことができます。 – Morrandir

1

このようなものは、反射を使用してトリックを行うことができます。

public final class MyEntity extends AbstractEntity{ 

    public static final ENTITY_1 = new MyEntity(1, "Entity 1", "foo"); 
    public static final ENTITY_2 = new MyEntity(2, "Entity 2", "bar"); 
    public static final ENTITY_3 = new MyEntity(3, "Entity 3", "baz"); 

    public static final Set<MyEntity> ALL; 

    static { 
     final Set<MyEntity> all = new TreeSet<>(); 

     // Find all static fields in this class which are instances of this class: 
     final Field[] fields = MyEntity.class.getDeclaredFields(); 
     for (Field f : fields) { 
      if (f.getType() == MyEntity.class) { 
      if (Modifier.isStatic(f.getModifiers()) { 
       all.add((MyEntity)f.get(null)); 
      } 
      } 
     } 

     ALL = Collections.unmodifiableSet(all); 
    } 

    private final String foo; 

    private MyEntity(int id, String name, String foo){ 
     super(id, name); 
     this.foo = foo; 
    } 
} 

一般的なユーティリティ関数initializeEntitySet(Class<?> entityClass)を書くことは簡単です。

+0

ありがとう、これは実際に動作します。 私は@Cristian Ramon-Cortesのソリューションが好きです。コンパイル時にすべてのインスタンスを知っているはずです。 – Morrandir

関連する問題