2012-03-24 9 views
2

多くのデザインブックでは、「実装ではないインターフェイスへのプログラム」という言葉が出てきました。これを遵守して密結合を排除することができ、抽象化も達成できます。私はシナリオを持っていますが、私はこれを実装したいと思いますが、私の限られた知識では分かりません。インターフェイスへのプログラミング

私はクラスといくつかのプロパティセットを持っていました。時間がたつと私の要求が変わり、ItemAssociatedToProductItemAssociatedToOffersという2つのプロパティを追加するよう強制されました。これらのプロパティを持つオブジェクトを作成すると、私は心配し、OfferクラスとProductクラスを継承してクラスを分割することに決めました。Itemクラスを継承しています。私は私のオブジェクトに具体的な実装を排除すると思った。だから、私のクラスで私はこのようなオブジェクトを作成したい、

Item myItem = new Product() // or Offer() 

私は抽象化を達成できるように。しかし、Itemクラスは、派生クラスが持つ追加のプロパティを持っていないので、私はそれを参照することはできません。私はタイプとタイプを識別するために "is"チェックを使用して、それを対応するオブジェクトにキャストすべきだと思った。しかし、再びその茂みの周りのビート。私のシナリオを解決する方法はありませんが、同時に抽象化を遵守するか、この原則はデータ(プロパティ)ではなく行動(メソッド/関数)に使用することのみを意図していますか?

アダム・リス - >それは今正しい?:)

class Program 
{ 
    static void Main(string[] args) 
    { 
     Item myProduct = new Product(); 
     myProduct.ProductName = "CellPhone"; 
     myProduct.ProductPrice = "$300"; 
     myProduct.ItemType = myProduct.GetProductOrOffer(); 

     Item myOffer = new Offer(); 
     myOffer.ProductName = "CellPhoneCover"; 
     myOffer.ProductPrice = "$0"; 
     myOffer.ItemType = myOffer.GetProductOrOffer(); 
    } 
} 

interface Item 
{ 
    String GetProductOrOffer(); 
    String ProductName 
    { 
     get; 
     set; 
    } 

    String ProductPrice 
    { 
     get; 
     set; 
    } 

    String ItemType 
    { 
     get; 
     set; 
    } 

} 

class Product : Item 
{ 
    public String GetProductOrOffer() 
    { 
     return "Product"; 
    } 

    public String ItemType 
    { 
     get; 
     set; 
    } 

    public string ProductName 
    { 
     get; 
     set; 
    } 

    public string ProductPrice 
    { 
     get; 
     set; 
    } 
} 

class Offer : Item 
{ 
    public String GetProductOrOffer() 
    { 
     return "Offer"; 
    } 

    public String ItemType 
    { 
     get; 
     set; 
    } 

    public string ProductName 
    { 
     get; 
     set; 
    } 

    public string ProductPrice 
    { 
     get; 
     set; 
    } 
} 
+0

変数を 'Product'または' Offer'型として宣言します。 'Item'は' Product'クラスや 'Offer'クラスについて知るべきではありません。 (新しいサブクラスを追加する場合、 'Item'を変更する必要はありません。)' ItemType'が実際の型を示す場合、コンストラクタは各クラスに対して適切に設定する必要があります。それは不変(const)でなければならず、 'GetProductOrOffer()'は実際に 'GetItemType()'です。 –

答えて

3

インターフェイスにプログラミングするときは、すべての実装クラスが特定のメソッドセットを提供するという契約を作成しています。つまり、Itemで動作するジェネリックコードを誰でも書くことができ、インターフェイスのプロパティのみを使用し、特定のタイプのItemを心配する必要はありません。

これは例で分かりやすいかもしれません。

interface Item { 
    getItemType(); 
    getName(); 
    getDescription(); 
    getPrice(); 
} 

class Product implements Item { 
    getItemType()  { return "Product"; } 
    getName()   { /* implementation here */ } 
    getDescription()  { /* implementation here */ } 
    getPrice()   { /* implementation here */ } 
    getManufacturer() { /* implementation here */ } 
    getWholesaleCost() { /* implementation here */ } 
} 

class Offer implements Item { 
    getItemType()  { return "Offer"; } 
    getName()   { /* implementation here */ } 
    getDescription()  { /* implementation here */ } 
    getPrice()   { /* implementation here */ } 
    getExpirationDate(); { /* implementation here */ } 
    getFinePrint();  { /* implementation here */ } 
} 

今、あなたはタイプProductOfferの変数を作成することができます。あなたはそれらを作成しているので、おそらくを実行します。は、そのタイプを気にするので、適切なクラスに保存してください。実際には、おそらくOfferの価格は曜日によって異なりますが、Productの価格は卸売費に応じて異なるため、一般的な方法を別々に実装することもできます。そのため、価格を別々に計算する必要があります。

しかし、誰もこのような唯一の引数がItemであることを気にジェネリック方法、書くことができます。これは、Product SまたはOffer秒のリストからカタログを印刷することができ

main() { 

    Product myProduct = new Product(); 
    myProduct.name = "SuperExtraPolyWidget"; 
    myProduct.description = "The best widget you can buy!"; 
    myProduct.price = 1428.57; 
    myProduct.manufacturer = "SuperExtra, Inc."; 
    myProduct.wholesaleCost = 314.15; 

    Offer myOffer = new Offer(); 
    myOffer.name = "WonderBargainDeal"; 
    myOffer.description = "The deal you've wondered about"; 
    myOffer.price = 0; 
    myOffer.expirationDate = Date(yesterday); 
    myOffer.finePrint = "Valid between 1:23 and 1:24 AM February 29."; 

    List<Item> itemList = List.of(myProduct, myOffer); 
    printCatalog(itemList); 
} 

printCatalog(List<Item> items) { 
    for (Item item in items) { 
    printf("%s: %s\n", item.getItemType(), item.getName()); 
    printf("------------------\n"); 
    printf("%s\n\n", item.getDescription()); 
    } 
} 

(またはこれは、Itemインターフェイスで定義されているメソッドのみを使用するためです。

+0

私が言ったのは、商品とオファーは "商品"です。だから私はそれを継承しました。インターフェイスへのプログラミング以来、私はちょうどこのようなオブジェクトを作成しました - > Item myItem = new Product()// Offer()。 ItemAssociatedToProductはProductクラスのプロパティであるため、myItemオブジェクトにはItemAssociatedToProduct(boolean)プロパティはありません。だから、インターフェイスでIsItProductOrOffer()メソッドのようなメソッドを持って、それを実装し、クラスを提供する必要がありますか? myItem.IsItProductOrOffer()を呼び出すと、prprtyを直接探すのではなく、自分のo/pを達成するために正確にwatを識別できるように任意の値が返されます – deen

+1

いいえ、私はあなたに 'Product myProduct = new Product()'または'myOffer = new Offer()'を提供するのは、その違いが重要なためです。 (そうでない場合は、より具体的な型の代わりに 'Item'を作成するだけです)。' Product'または 'Offer'に固有のプロパティを気にするメソッドは、それらの型を引数として取るべきです。しかし共通のプロパティだけを扱う_generic_メソッドは 'Item'引数を取るべきです。 'Item'は' Product'と 'Offer'サブクラスについて知りません。 –

+0

私はあなたが言うことを理解していないことをあなたに伝えて本当に申し訳なく思っています。あなたは私をコード化し、私が使ったのと同じクラスとインターフェイスで見せることができますか? – deen

2

継承は、意味があり、ドメインオブジェクトをモデル化するのに適切な方法である場合にのみ使用することが重要です。製品とオファーは、「is-a」関係がある場合にのみ商品を実装すべきです:商品は商品、商品は商品です。

その場合ですか?アプリケーションの詳細がわからないと、わからないことがあります。しかし、私はItemが商品の一般的なタイプの特定の注文アイテムを表すいくつかのコマースアプリを開発しました。その場合、商品はアイテムではありませんでした。 Itemは、そのItemが表す特定のタイプのProductを参照するProduct属性を持つことができます。同様にオファーの場合 - オファーがアイテムでない場合、それは別のクラスでなければならず、Itemはそのアイテムの購入に使用されたオファーにそれを関連付けるアトリビュートを持つでしょう。

あなたのシステムでProductとOfferが本当にItemsである場合、それはおそらくモデルを作成する正しい方法でしょう。製品とオファーの両方で実装できる関連するメソッドをItemに与えるだけで済みます。キャストする必要がある場合もありますが、その前にこのような状況に陥っている場合もあります。

結論として、モデリングがこれらのオブジェクトの表現に合っていることを確認してください。

関連する問題