2012-05-04 57 views
0

這可以通過一個例子更好地解釋。目前,我有這樣的事情:如何強制執行接口方法中的特定值?

public class Car { 
    internal string SaleCode {get; set;} //Spring, Summer, ... 
    public string Name {get; set; } //Model name 
} 

public interface ICarFactory 
{ 
    Car GetSummerSaleCar(); 
    Car GetSpringSaleCar(); 
} 

public class FordFactory : ICarFactory 
{ 
    public Car GetSummerSaleCar() { 
     return new Car() {Name="Fiesta"}; 
    } 
    public Car GetSpringSaleCar() { 
     return new Car() {Name="Fusion"}; 
    } 
} 

public class CarProvider { 
    public void ProduceCars(ICarFactory factory) { 
     var inventory = new List<Car>(); 
     Car car = null; 
     car = factory.GetSummerSaleCar(); 
     car.SaleCode = "SMR"; 
     inventory.Add(car); 

     car = factory.GetSpringSaleCar(); 
     car.SaleCode = "SPG"; 
     inventory.Add(car); 
    } 
} 

汽車的SaleCode應該始終爲每個方法是相同的,所以CarFactory實現不應設置此值。現在我在CarProvider類中設置了它,但是我想知道是否有辦法從接口中獲取它。我能想到的唯一的事情就是使用一個屬性應用於我可以設置類型的接口內部的方法定義,但我覺得必須有另一種選擇。

想法?

UPDATE

在你想知道的情況下,這就是我說的是,當我提到添加屬性接口中的每個方法:

public class SaleAttribute : Attribute 
{ 
    public string Code { get; set; } 
} 


public interface ICarFactory 
{ 
    [Sale(Code = "SMR")] 
    Car GetSummerSaleCar(); 
    [Sale(Code = "SPG")] 
    Car GetSpringSaleCar(); 
} 

public void ProduceCars(ICarFactory factory) 
{ 
    var inventory = new List<Car>(); 
    foreach (var method in typeof(ICarFactory).GetMethods()) 
    { 
     String carType = null; 
     var attributes = method.GetCustomAttributes(typeof(SaleAttribute), false); 
     if (attributes.Length == 1) 
     { 
      saleCode = ((SaleAttribute)attributes[0]).Name; 
      Car car = (Car)method.Invoke(factory, null); 
      car.SaleCode = saleCode; 
      inventory.Add(car); 
     } 
    } 
} 

這有額外的好處如果在界面中添加了一個方法,CarProvider不需要修改。顯然缺點是與Reflection相關的開銷(性能和維護)。

UPDATE2

我使用汽車類型銷售代碼,因爲這更能體現我的情況發生變化的例子。

+1

如何實現接口並設置汽車類型的抽象基類? –

+3

爲什麼在創建Car對象期間無法設置Type的任何特定原因? –

+0

您可以自動設置Car類中的值,也可以使用抽象類而不是接口。您的FordFactory也不實現ICarFactory。 – MrFox

回答

3

邁克我認爲最好的方法是有一個抽象類型Car和兩個派生類:CompactCar和MediumCar。

public abstract class Car { 
    internal string Type {get; protected set;} //Compact, Medium, Large, ... 
    public string Name {get; set; } //Model name 
} 

public class CompactCar : Car 
{ 
    public CompactCar() { this.Type = "Compact"; } 
} 

public class MediumCar : Car 
{ 
    public MediumCar() { this.Type = "Compact"; } 
} 

所以,你可以返回的特定類型,如:

public interface ICarFactory  
{  
    CompactCar GetCompact();  
    MediumCar GetMedium();  
} 
public class FordFactory : ICarFactory  
{ 
    public CompactCar GetCompact() { 
     return new CompactCar() {Name="Fiesta"}; 
    } 
    public MediumCar GetMedium() { 
     return new MediumCar() {Name="Fusion"}; 
    } 
} 

這使用它,因爲它仍可以參考汽車行駛抽象類型的車在源代碼中的影響降到最低。

+0

這絕對是一個不錯的選擇。唯一的事情是,在我的實際實現中,我實際上有10到15種類型,所以這意味着要創建10到15個類。我在尋找一些東西,當添加一個新的類型時,代表了代碼中最小的變化量。但這可能是不可行的... – Mike

+0

沒有辦法在界面中添加一些邏輯。但是,不同的返回類型實際上是在界面中創建一個規則。我沒有看到任何其他方式來滿足您的要求。 – 2012-05-04 20:00:17

+0

那麼,我可以想到一種方法,那就是使用屬性。查看我的問題中的更新。但我不確定這是最好的選擇。 – Mike

0

CarType.Create(Medium)而不是new Car

我建議一個工廠叫CarType

public class CarType{ 
    public class CarType(instName){ 
     this.instName = instName; 
    } 
    public Car Create(){ 
     return new Car(){Type=instName;} 
     //or alternatively, if you have more implementations for the cars 
     //return (Car)Activator.CreateInstance(this.instName); 
    } 
    public static CarType Compact = new CarType("Compact"); 
    public static CarType Medium = new CarType("Medium"); 
} 

和用法是

Medium.Create(){Name="Fiesta";} 

但是,這仍然是CarFactorys方法中,因此不適合你多大的幫助?

+0

混凝土汽車工廠不應該能夠設置汽車類型。 – Mike

+0

i ment CarType作爲設置類型的汽車的工廠...我正在考慮本書中的「類型 - 工廠」模式:http://media.pragprog.com/titles/dhnako/toc.pdf – mindandmedia

+0

你能否詳細說明一下?我沒有看到你鏈接到的pdf中的很多細節。 – Mike

相關問題