2012-08-30 28 views
0
public interface IRecord 
{ 

} 

public class BirthRecord : IRecord 
{ 
    public string CityOfBirth; 
    public Date DateOfBirth; 
    public BirthRecord(string cityOfBirth, Date dateOfBirth) 
    { 
     // assign these to properties 
    } 
} 

public class CarRecord : IRecord 
{ 
    public Color Color; 
    public string Manufacturer; 
    public CarRecord(Color color, string manufacturer) 
    { 
     // assign these to properties 
    } 
} 

public interface IAccount 
{ 
    public List<IRecord> Records { get; set; } 
} 

public class Client 
{ 
    public void ProcessAccount(IAccount account) 
    { 
     foreach(IRecord record in account.Records) 
     { 
      if(record is CarRecord) 
       handleCarRecord((CarRecord)record); 
      else if(record is BirthRecord) 
       handleBirthRecord((BirthRecord)record); 
     } 
    } 
} 

因此,當你到達客戶端並想要處理值對象時,你必須做各種凌亂的類型檢查和轉換 - 這是一種可接受的模式,還是我正在犯一個更基本的設計錯誤?這似乎違反了OCP,如果不是其他OOD原則。有沒有其他的選擇?使用多態性傳遞值對象是一種不好的做法?

+0

你想做什麼?你能提供一個更大的圖片,所以人們會試圖回答? – DarthVader

+0

更好嗎? – Ford

+0

Baconator,很好。 – Pacane

回答

2

您提供的方法稱爲訪問者模式,但Visitor用於在複雜的數據結構上創建抽象算法,以便您擁有模板算法並只提供它的具體實現。

public abstract class AbstractAccountVisitor {  

    public void ProcessAccount(IAccount account)  
    {   
    foreach(IRecord record in account.Records)   
    {    
     if(record is CarRecord)     
      handleCarRecord((CarRecord)record);    
     else if(record is BirthRecord)     
      handleBirthRecord((BirthRecord)record);   
    }  
    } 

    public abstract void handleCarRecord(CarRecord record); 
    public abstract void handleBirthRecord(BirthRecord record); 

} 

它可以讓你有

public class ConcreteAccountVisitor : AbstractAccountVisitor { 

    public override handleCarRecord(CarRecord record) { 
     // do something concrete with carrecord 
    } 

    public override handleBirthRecord(BirthRecord record) { 
     // do something concrete with birthrecord 
    } 

} 

// client 
AbstractAccountVisitor visitor = new ConcreteAccountVisitor(); 

visitor.ProcessAccount(account); 

注意,通過封裝在基訪問者算法的核心,你允許只覆蓋其處理特定類型的記錄方法來定製加工。

還要注意,而不是提供一個遊客的,你可以介紹一下處理類:在可能的操作對你的對象列表中被稱爲建議

public interface IRecord { 
    void Operation(); 
}    

public class AccountProcessor {  

    public void ProcessAccount(IAccount account)  
    {   
    foreach(IRecord record in account.Records)   
    {    
     record.Operation(); 
    }  
    } 
} 

這種更簡單的方法,這樣就可以介紹界面合同中的所有操作。另一方面,訪問者允許您在您的課程/界面上引入任意數量的操作,因爲您只需提供新的具體訪問者。

+0

確實非常酷。我正在爲此閱讀wiki,並注意到它表示它應該是幫助您遵循OCP的一種很好的模式,但這似乎相當違反直覺...通過查看您的示例和wiki,它看起來像任何時候都想要添加更多類以供訪問者處理,您必須修改源代碼,從而違反OCP。我錯過了什麼? – Ford

+1

真實的觀察。這就是爲什麼Acyclic Visitor已被提議。這是對訪問者的一個稍微修改,它比較複雜,但沒有你描述的問題。 –

相關問題