6

次のことを考慮してください。

  public abstract class Item {
     String name;
     String description;
     //concrete getters and setters follow
  }

   public class InventoryItem extends Item {
     //empty subclass of Item 
   }

  public class CartItem extends Item {
     int quantity;
     int tax;
     //getters and setters for quantity and tax follow
  }

InventoryItemは販売可能なアイテムを表し、CartItemはカートに追加されるアイテムを表すため、数量や税金などの追加のプロパティがあります。このシナリオでは、抽象クラスItemの空のサブクラスがあっても大丈夫ですか?

オプション2:空のItemインターフェースを持つことができます。InventoryItemはItemを実装し、名前と説明のプロパティを定義し、ゲッターとセッターを持ちます。CartItemはInventoryItemから拡張され、数量と税金をプロパティとして定義し、ゲッターとセッターがあります。

オプション3:アイテムインターフェイスがある方が良いでしょうか。InventoryItemはItemを実装します。次に、'has-an' Itemと2つのプロパティ、つまり税金と数量を持つCartItemクラスを作成できます。

4

2 に答える 2

5

この設計には何の問題もないと思います。Itemベースとして、およびInventoryItem/CartItemインスタンス化可能なクラスとして明確に指定されています。クラスの使用目的が他のクラスのベースとして使用されるという事実を強調するために、名前Itemを(Javaクラスライブラリがこれを行う)に変更します。AbstractItem

C ++には、ベースポインタを介した割り当てなど、すべての「非リーフ」クラスを抽象化することが非常に望ましい特定の問題があります。ルールは文字通りJavaに変換されませんが、クラスが自給自足であっても、非リーフクラスを抽象化することは依然として良い考えだと思います。これは、直接インスタンス化を目的としたクラスと拡張を目的としたクラスを明示的に分離するのに役立ちます。これは、コードベースに精通していない人によるメンテナンスに適しています。

ルールをさらに一歩進めて、Javaではすべてのリーフクラスを作成するのが一般的な方法finalです。これは、特にクラスが不変である場合に、優れた防御ルールです。

編集:カート内のアイテムのモデリングに関する限り、継承は最良のオプションではありません。実際、それは間違ったことだと思います。カートに入れても別の種類の物にはならないので、拡張するのではなく、CartItem自分で作ってみます。Itemこれが私がどのようにモデル化されるべきだと思うかです:

public class Item {
    String name;
    String description;
    ...
}

public class CartItem {
   Item item;
   int quantity;
   int tax;
   ...
}
于 2012-08-02T18:17:01.273 に答える
1

少し長い提案、または意見を提供させてください。それはいくつかのガイダンスを提供するかもしれません。

階層を設計するとき、私はポリモーフィズムによる振る舞いだけを区別する傾向があります。一般的に、私はデータのみによるオブジェクトの区別を避ける傾向があります。何年にもわたって、構造体のような「データオブジェクト」の継承階層を、それらが保持する変数のみに基づいて作成することをやめました。

私が最も時間を費やしているのは、メソッドの観点から表現する抽象化クラスの共通インターフェイスを定義し、すべて同じインターフェイスに対応できるサブクラスを作成することですが、動作は異なります。(リスコフの置換原則)

この場合、在庫の方法や税金の計算方法などが異なるItem実装の階層を持つ共通のインターフェイス/抽象Itemクラスを検討します。アイテムがどこにあるかまたは何を教えてくれるメソッド.isInCatalog()を使用できます。別の方法で処理する必要がある場合はその性質ですが、それでも、アイテムタイプ固有のロジックのほとんどをそのポリモーフィックメソッドの実装にカプセル化しようとします。

これらのタイプの計算は通常、実際には単一のオブジェクトではなくデータベースのバッチ/集計操作で実行されますが、抽象レベルで.getTax()、. getQuantity()を実行し、異なる動作のサブクラスを作成します。 。(nullの処理を回避するために何もしないためにNullObjectリファクタリングを検討してください)

この設計を支援するいくつかの原則は、この堅実なブログ投稿で概説されています。

http://codebork.com/2009/02/18/solid-principles-ood.html

于 2012-08-02T19:26:59.650 に答える