2012-03-24 39 views
2

我在許多設計書中遇到了'程序到界面而不是執行'這一行。通過堅持這一點,我們可以消除緊密耦合,我們也可以實現抽象。我有一個場景,我想實現這一點,但不知道我有限的知識。編程到一個接口

我有一個類和一些屬性集。經過一段時間後,我的要求發生了變化,並被迫添加了一個名爲ItemAssociatedToProductItemAssociatedToOffers的兩個屬性。使用這些屬性創建對象會讓我擔心,並決定通過讓Offer類和Product類繼承Item類來拆分類。我認爲要消除具體的實現我的對象。所以在我的UI類我想創建一個這樣的對象,

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

這樣我就可以實現抽象了。但由於Item類不具有派生類所具有的其他屬性,因此我無法引用它。我以爲我應該使用「is」檢查來識別類型並將其類型轉換爲相應的對象。但它又一次擊敗了灌木叢。是不是有辦法解決我的情況,但同時堅持抽象或這個原則只是爲了將它用於行爲(方法/功能)而不是數據(屬性)?

Adam Liss - >現在是否正確:)?

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()'。 – 2012-03-24 11:17:34

回答

3

當您編程到接口時,您正在創建一個契約,表明每個實現的類將提供一組特定的方法。這意味着任何人都可以編寫在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 */ } 
} 

您可以創建Product類型和Offer的變量。既然你正在創建它們,你可能會在中關心它們的類型,所以你將它們存儲在相應的類中。實際上,您甚至可能採用不同的常用方法,因爲Offer的價格可能取決於一週中的某一天,但Product的價格取決於其批發成本,因此您需要以不同方式計算價格。

但是,任何人也可以寫一個通用方法只在乎它的參數是一個Item,像這樣:

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()); 
    } 
} 

這可以打印從Product S或Offer個列表中的目錄(或兩者),因爲它只使用Item界面中定義的方法。

+0

我的意思是,產品和提供「是」項目。所以我繼承了它。由於編程到一個接口,我只是創建了這樣的對象 - > Item myItem = new Product()//或Offer()。由於ItemAssociatedToProduct是Product類的屬性,因此對象myItem將不具有ItemAssociatedToProduct(boolean)屬性。所以你的意思是,我應該在界面中使用IsItProductOrOffer()方法,並實現它的產品並提供類?並調用myItem.IsItProductOrOffer()將返回任何值,所以我可以確定它完全是爲了實現我的o/p而不是直接尋找prprty – deen 2012-03-24 09:59:22

+1

不,我的意思是你應該分配'Product myProduct = new Product()'或'提供myOffer = new Offer()',因爲差異很重要。 (如果他們不是,你只需要創建一個'Item'而不是一個更具體的類型。)關注'Product'或者'Offer'特定屬性的方法應該將這些類型作爲參數。但只關心公共屬性的_generic_方法應該使用'Item'參數。一個'Item'不會(也不應該)知道'Product'和'Offer'子類。 – 2012-03-24 11:08:41

+0

我真的很抱歉告訴你,我不明白你說的話。你能編碼我,並顯示與我使用的相同類和接口嗎? – deen 2012-03-24 20:12:47

2

只有在有意義的情況下使用繼承纔是重要的,並且是對域對象建模的適當方法。如果存在「是-α」關係,則產品和供應應僅實現項目:產品是項目,而供應是項目。

是這樣嗎?不知道你的應用程序的細節我們並不知道。但是我曾經在一些商務應用程序中使用Item來代表一般產品類型的特定訂單項目,在這些情況下,產品根本不是項目。項目可能具有產品屬性,指的是該項目所代表的產品的特定類型。同樣,對於商品 - 如果商品不是商品,它應該是一個單獨的類,並且商品可能具有與用於購買該商品的商品相關的屬性。

現在如果在您的系統中,產品和報價確實是項目,那麼這可能是對它們進行建模的正確方法。您只需要爲Item提供Product和Offer可以實現的相關方法。而且可能有些情況下你必須演員,我們以前都遇到過這種情況。

總之,只要確保你的建模是正確的這些對象代表。