男人這個答案真的增長了,但它很有趣。這裏我們去:)
我同意這是一個非常複雜的設計。當你使用它們來「抽象變化」時,接口是有幫助的,但在這個例子中,所有東西都是抽象的。這是一個非常難以遵循的例子,所以這應該是一個很大的指標,說明某些事情是錯誤的。意大利麪條代碼的反面是寬麪條代碼(對許多層),這正是這張圖的內容。我可以看到你有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()
而且類圖會是這個樣子。 
好吧,這一切都很好,但爲什麼所有額外的工作固體需要。讓我們看看最終的實現。
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
}
您的意思是鮑勃馬丁的固體原則。 Martin Fowler傾向於寫設計模式。 – Oded 2010-08-17 16:36:44
Nah,Martin Fowler是來自EastEnders的那個瘋狂的傢伙 – fletcher 2010-08-17 16:44:29
哦,是的......我不知道爲什麼我總是把這兩個混在一起。我用正確的人解決了這個問題。 – 2010-08-18 02:52:54