40

どのクラス設計が優れているか、またその理由は?

public class User
{
    public String UserName;
    public String Password;
    public String FirstName;
    public String LastName;
}

public class Employee : User
{
    public String EmployeeId;
    public String EmployeeCode;
    public String DepartmentId;
}

public class Member : User
{
    public String MemberId;
    public String JoinDate;
    public String ExpiryDate;
}

また

public class User
{
    public String UserId;
    public String UserName;
    public String Password;
    public String FirstName;
    public String LastName;
}

public class Employee
{
    public User UserInfo;
    public String EmployeeId;
    public String EmployeeCode;
    public String DepartmentId;
}

public class Member
{
    public User UserInfo;
    public String MemberId;
    public String JoinDate;
    public String ExpiryDate;
}
4

11 に答える 11

60

この質問は、継承が「IS-A」関係をモデル化し、メンバーシップが「HAS-A」関係をモデル化することを認識することによって簡単に答えられます。

  • 従業員はユーザーです
  • 従業員はユーザー情報を持っています

どちらが正しいですか?これがあなたの答えです。

于 2008-09-02T04:41:11.573 に答える
20

どちらも好きじゃない。誰かがメンバーと従業員の両方である場合はどうなりますか?

于 2008-09-02T04:39:28.673 に答える
17

次のことを自問してください。

  • Employee IS a User をモデル化しますか? その場合は、継承を選択してください。
  • ユーザー情報を持つ従業をモデル化しますか? その場合は、コンポジションを使用してください。
  • ユーザー (情報) と従業員の間に仮想機能が含まれていますか? その場合は、継承を使用してください。
  • Employee は User (info) の複数のインスタンスを持つことができますか? その場合は、コンポジションを使用してください。
  • Employee オブジェクトを User (info) オブジェクトに割り当てるのは理にかなっていますか? その場合は、継承を使用してください。

一般に、コードの複雑さと必要な効率の制約の下で、プログラムがシミュレートする現実をモデル化するよう努めてください。

于 2008-09-02T05:03:48.960 に答える
13

良い質問ですが、善悪について気を散らすことを避けるために、各アプローチの長所と短所を尋ねることを検討します. ともかく ....

最初のアプローチ別名継承

長所:

  • ポリモーフィックな動作を許可します。
  • 最初はシンプルで便利です。

短所:

  • より多くの動作や関係が追加されると、時間の経過とともに複雑または不器用になる可能性があります。

第二のアプローチ別名構成

長所:

  • リレーショナル テーブル、構造化プログラミングなどの非 oop シナリオに適切に対応
  • リレーションと動作を段階的に拡張するのは簡単です (必ずしも便利である必要はありません) 。

短所:

  • ポリモーフィズムがないため、関連する情報と動作を使用するのはあまり便利ではありません

これらのようなリスト + Jon Limjapが言及した質問は、意思決定を行い、開始するのに役立ちます。そうすれば、正しい答えがどうあるべきかを見つけることができます ;-)

于 2008-09-09T04:07:23.107 に答える
12

構成が継承よりも常に優れているとは思いません(通常は)。従業員とメンバーが実際にユーザーであり、相互に排他的である場合は、最初の設計の方が適しています。従業員のユーザー名にアクセスする必要があるシナリオを考えてみましょう。2番目のデザインを使用すると、次のようになります。

myEmployee.UserInfo.UserName

これは悪い(デメテルの法則)ので、次のようにリファクタリングします。

myEmployee.UserName

これには、Userオブジェクトに委任するためにEmployeeに小さなメソッドが必要です。これらはすべて、最初の設計では回避されています。

于 2008-09-02T05:46:09.577 に答える
5

本当の質問は次のとおりです。

  • ユーザーの背後にあるビジネス ルールとユーザー ストーリーは何ですか?
  • 従業員の背後にあるビジネス ルールとユーザー ストーリーとは?
  • メンバーの背後にあるビジネス ルールとユーザー ストーリーは何ですか?

これらは 3 つの完全に無関係なエンティティであるかどうかであり、最初または 2 番目の設計が機能するかどうか、または別の完全に異なる設計が適切であるかどうかが決まります。

于 2008-09-02T05:43:14.420 に答える
4

どっちでもいいじゃない。可変状態が多すぎます。無効または部分的に初期化された状態にあるクラスのインスタンスを構築することはできません。

そうは言っても、継承よりも構成を優先するため、2 番目の方が優れています。

于 2008-09-02T04:47:39.840 に答える
3

要件/仕様を述べると、「最適な設計」に到達するのに役立つ場合があります。
現時点では、あなたの質問はあまりにも「読者の解釈の対象」です。

于 2008-09-02T07:43:01.197 に答える
2

考えるべきシナリオは次のとおりです。

同じユーザーが従業員とメンバーの両方になることができる場合は、構成 (2 番目の例) が適しています。なんで?同じ User を表す 2 つのインスタンス (Employee と Member) の場合、User データが変更された場合、2 つの場所で更新する必要がないためです。User インスタンスのみにすべての User 情報が含まれており、それのみを更新する必要があります。Employee クラスと Member クラスの両方に同じ User インスタンスが含まれているため、どちらにも更新された情報が自動的に含まれます。

于 2008-09-02T07:54:57.707 に答える
0

さらに 3 つのオプション:

  1. クラスUserに従業員とメンバーの両方の補足情報を含め、未使用のフィールドを空白にします (ID特定のUserは、ユーザーが従業員、メンバー、両方、またはその他であったかどうかを示します)。

  2. Userへの参照を含むクラスがありISupplementalInfo、は、などISupplementalInfoによって継承されます。すべてのユーザーに適用可能なコードはクラス オブジェクトを操作でき、参照を持つコードはユーザーの補足情報にアクセスできますが、このアプローチでは将来、補足情報の異なる組み合わせが必要になった場合に変更する必要がないようにします。ISupplementalEmployeeInfoISupplementalMemberInfoUserUserUser

  3. 上記と同様ですが、Userクラスにある種の のコレクションを含めISupplementalInfoます。このアプローチには、実行時にユーザーへのプロパティの追加を容易にするという利点があります (たとえば、Member採用された場合など)。前のアプローチを使用する場合、プロパティのさまざまな組み合わせに対してさまざまなクラスを定義する必要があります。「メンバー」を「メンバー+顧客」に変えるには、「従業員」を「従業員+顧客」に変えるのとは異なるコードが必要になります。後者のアプローチの欠点は、冗長または一貫性のない属性を防ぐのが難しくなることです (Dictionary<Type, ISupplementalInfo>補足情報を保持するために a のようなものを使用するとうまくいく可能性がありますが、少し「かさばる」ように見えます)。

直接継承よりも将来の拡張が可能になるという点で、私は 2 番目のアプローチを好む傾向があります。単一のオブジェクトではなくオブジェクトのコレクションを操作するのは少し面倒かもしれませんが、そのアプローチは他の方法よりも変化する要件を処理できる可能性があります。

于 2012-10-29T15:36:42.547 に答える