2010-08-17 30 views
2

我試圖第一次堅守Robert Martin的SOLID設計原則,但我並不擅長。需要關於.Net SOLID設計的幫助

實質上,我需要一個「節點」對象的層次結構。一些節點是NodeHosts,一些是NodeChildren,一些是Both。每個人都這樣做過,但我無法弄清楚如何做到這一點不固過於複雜的設計,還是進行節點亞型是這樣的:

INodeHostType node; 
public INodeType NodeType 
{ 
.... 
     set 
     { 
      node = (INodeHostType)value; 
     } 
} 

這違反了里氏替換原則吧?什麼是更好的方法? 這是我現在擁有的。 alt text

+0

您的意思是鮑勃馬丁的固體原則。 Martin Fowler傾向於寫設計模式。 – Oded 2010-08-17 16:36:44

+2

Nah,Martin Fowler是來自EastEnders的那個瘋狂的傢伙 – fletcher 2010-08-17 16:44:29

+0

哦,是的......我不知道爲什麼我總是把這兩個混在一起。我用正確的人解決了這個問題。 – 2010-08-18 02:52:54

回答

4

男人這個答案真的增長了,但它很有趣。這裏我們去:)

我同意這是一個非常複雜的設計。當你使用它們來「抽象變化」時,接口是有幫助的,但在這個例子中,所有東西都是抽象的。這是一個非常難以遵循的例子,所以這應該是一個很大的指標,說明某些事情是錯誤的。意大利麪條代碼的反面是寬麪條代碼(對許多層),這正是這張圖的內容。我可以看到你有3組。

  • 節點(子女,父母等)
  • 節點類型
  • 渲染

讓我們開始與節點,其真實的SOLID告訴你的代碼的接口,但並不一定意味着它必須是一個實際的界面。使用擴展基本節點的子節點使用常規舊繼承是完全可以接受的。這仍然是固體,在這種情況下是合理的。

public class Node 
{ 

    public var NodeType { get; set; } 
    public var DisplayText { get; set; } 
    public IRenderable Renderer { get; set; } 

    public Node() 
    { 
     // TODO: Add constructor logic here 
    } 

    public void Render() 
    { 
     Renderer.Render(); 
    } 
} 

public class ChildNode : Node 
{ 
    public var Owner {get; set;} 
    public var Sequence {get; set;} 

    public ChildNode() 
    { 
     NodeType = "Child"; //use an enum 
     DisplayText = "nom nom nom babies"; 
     Renderer = new ChildRenderer(); 
    } 
} 

//Parent Node is more of the same 

對於節點類型,其真正的節點有不同的類型,但它們都仍然有型。我認爲這不符合單獨的抽象。我剛剛將類型轉移到您的基本節點。

//This didn't add value so its just an enum used in the baseclass now 

對於渲染,現在你是要發生什麼。由於ChildNodes和ParentNodes的渲染方式不同,因此將其抽象化是有意義的。雖然,我看到的是,在IRenderer所有屬性中IRenderContext是重複的,所以我只是要他們摺疊成1

interface IRenderable 
{ 
    //properties 
    // TODO: Add properties here 

    //methods 
    void Render(); 
} 

interface ChildRenderer : IRenderable 
{ 
    void Render() 
    { 
     //Render Me Here 
    } 
} 

//ParentRender() is more of the same 

//I could add all sorts of functionallity with out touching other code 
//  ManChildRenderer(), TripletsChildRenderer() 

而且類圖會是這個樣子。 Solid Example

好吧,這一切都很好,但爲什麼所有額外的工作固體需要。讓我們看看最終的實現。

public static void main() 
{ 
    //if this isnt acceptle instantiation use a NodeFactory 
    Node node1 = new ParentNode(); 
    Node node2 = new ChildNode(); 

    //Now we don't care about type -- Liskov Substitution Principle 
    node1.Render(); 
    node2.Render(); 

    //adding or changing functionality is now non-breaking 
    node1.Renderer = new ManChildRender(); 
    //I've added a whole new way to render confident I didnt break the old renders 
    //In fact I didn't even upon those class files 
} 
+0

+1 TL; DR,但是+1。希望其他人會認爲適當的表彰和努力和/或提供批評,如果有必要的話...... – 2011-03-19 00:34:21

+0

如果你跳過代碼示例它不壞。我認爲他們對提問者的理解很重要:) – Evan 2011-03-19 01:01:50

+0

+1在這一點上真的很努力。仍在思考影響。我沒有聽到別人的消息,我走了一條不同的路線,所以也許我們可以通過比較。 – 2011-03-21 13:26:12