2010-02-03 60 views
2

我有一個關於設計模式的小問題哪種設計模式可以做到這一點?

我有這兩個類從相同的類(doctrine_record)擴展,所以他們主要有相同的方法和功能,但是,他們現在有不同的屬性。我想創建一個包含2個類的總和屬性的包裝器,我記得有一個這樣的模式,但我一直在翻閱這本書,卻找不到它。我基本上試圖做的是map屬性,但是由於每個類都將它們的數據存儲在不同的表中,我必須經常爲每個表調用相同的方法(save()),因爲將會有大量的我是一些如何結婚的類,我不想爲每一對類我都寫完整的代碼。你有什麼建議,我該如何歸檔這個?

爲了讓自己更清楚,我將添加一個簡單的例子

我有這2

class Content extends doctrine_record 
{ 
    int content_id; 
    date create_date; 
    date modified_date; 
    int number_clicks; 
    Content_translations translations[]; 
} 

class Content_translations extends doctrine_record 
{ 
    int translation_id; 
    int content_id; 
    string language; 
    string content; 
    string title; 
} 

,你可以看到,1 內容可以有N個Content_translations,因爲它變得一個非常重複的任務,與特定的翻譯工作,我需要一些特定的內容我想合併這兩個類,避免修改任何的2.

我試圖讓我告訴一個類(如果在運行時更好),我將它們合併爲2個類,因此如果我實例化某個內容(讓我們調用這個新的類部分),它將具有這兩個類的屬性。如果我調用save()方法,我不得不在兩個對象上調用它,我記得有一個這樣的模式,但我不記得它的名字。

什麼基本上,我想在這裏做的是下面,就讓我們說我實例的部分(該部分的類是類我試圖創建)

所以如果我這樣做,我會得到我的內容和相關的中英翻譯,我甚至可以訪問兩個

$section = new Section('1','en'); 
echo $section->number_clicks; 
echo $section->title; 

的屬性,如果我修改其中的任何和調用save()方法

$section = new Section('1','en'); 
$section->number_clicks = $section->number_clicks+1; 
$section->title = "new title"; 
$section->save(); 

這會調用每個的我2包含的類(內容和content_translations),使信息的保存()方法是在2個不同的錶店,現在如果我這樣做

$section = new Section('1','es'); 
$section->title = "titulo en español"; 
$section->save(); 

這隻會改變content_translations對象罪我實例化在「ES」版我的對象

的希望你能幫助我:)感謝提前

+1

能否請你告訴你想什麼能夠與上面顯示的兩個類做的代碼? – Jay 2010-02-03 02:15:12

+0

剛剛添加了一個例子:) – perrohunter 2010-02-03 02:25:53

回答

1

是不是真的有這樣做的一個設計模式 - 你只需要使用你的分析能力就這一個。

如果你有相同的方法,但不同的領域,我會使用一個叫做attributes的Hashtable。您可以檢查屬性的存在。其中一個屬性可以是type來區分它們。

如果只有少數幾種類型,你可能有多種類型,但是如果你想添加10個以上的話,它看起來就像overclassing。

1

爲了解決您的問題,我計算了三種設計模式:Adapter,Composite,Factory Method

我提出的解決方案類似的東西:

///Adapter. To adopt current classes to specific hierarchy 
abstract class AbstractSection 
{ 
    public void Save(); 
} 

class TranslateSection : AbstractSection 
{ 
    public override void Save() 
    { 
    //saves current translate version 
    } 
} 

class ConcreteSection : AbstractSection 
{ 
    public ConcreteSection(IEnumerable<TranslateSection> translates) 
    { 
    translates.AddRange(translates); 
    } 
    //For simplification only! 
    public ConcreteSection(TranslateSection translates) 
    { 
    translates.AddRange(translates); 
    } 
    public ConcreteSection() 
    { 
    } 
    public override void Save() 
    { 
    SaveCurrentSection(); //Save current ConcreteSection 
    //Save translates 
    foreach(var t in translates) 
     t.Save(); 
    } 

    //Slitly modified Composite pattern 
    private List<TranslateSection> translates = new List<TranslateSection>(); 
    private Content content; 

    //To inner content we can access directly: 
    Content GetContent() {return content;} 
    Content Content { get {return content;} } 
    //Or we can wrap this with some methods (or something else) 
    int GetContentId() {return content.content_id;} 
    void SetContentId(int contentId) {content.content_id = contentId;} 

    //To simplify access to translate sections we can use something like this 
    TranslateSection GetTranslateSection() {return translates[0];} 
} 

//Factory method design pattern to simplify object creation 
class SectionFactory 
{ 
    public static AbstractSection Create(string locale) 
    { 
    //dependend on locale (or locales) we can create 
    //one or more translates 
    if (locale == 'en') 
     return new ConcreteSection(CreateEnglishTranslateSection()); 
    //in some circumstances we need only simple section 
    //without translates 
    return new ConcreteSection(); 
    } 
} 

用法:

var section = SectionFactory::Create('en'); 
section.Save(); //here we save both sections 
Console.WriteLine(section.number_clicks); 
Console.WriteLine(section.GetTranslation().title); 

var section = SectionFactory::Create('es'); 
section.Save(); //saves only 'es' section 
Console.WriteLine(section.number_clicks); //we can access to this field (or property) 
Console.WriteLine(section.GetTranslation().title); //here we got runtime failure!