这样做的设计模式是什么?

时间:2010-02-03 02:10:01

标签: oop design-patterns

我对设计模式有一个小问题

我有两个类从同一个类(doctrine_record)扩展,因此它们主要具有相同的方法和功能,但是它们现在具有不同的属性。我想创建一个暴露2类总和属性的包装器,我记得有一个模式,但我一直在浏览这本书,却找不到它。我基本上要做的是映射属性,但是由于每个类都将它们的数据存储在不同的表中,我必须经常为每个表调用相同的方法(save()),因为会有很多我有些如何结婚的课程我不想为每一对课程编写完整的代码。您对如何存档有任何建议吗?

为了让自己更清楚,我将添加一个简单的例子

我有这两个

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个类。

我正在尝试拥有一个我告诉的类(如果在运行时更好)我拥有的两个类并且它合并了em,所以如果我实例化某个内容(让我们调用这个新的类部分)它会有两个类属性。如果我调用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();

这将在我的两个包含的类(content和content_translations)中调用save()方法,因此信息存储在2个不同的表中,现在如果我这样做

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

这只会改变content_translations对象犯罪我实例化我的对象的'es'版本

希望你能帮助我:)并提前感谢

2 个答案:

答案 0 :(得分:1)

对此没有真正的设计模式 - 你只需要在这个上使用你的分析技能。

如果您使用相同的方法但不同的字段,我会使用名为attributes的Hashtable。您可以检查属性是否存在。其中一个属性可能是type来区分它们。

如果只有少数几种类型,你可能会进行多类化,但如果你想添加超过10的类型,它似乎会过度分类。

答案 1 :(得分:1)

要解决您的问题,我会计算三种设计模式:AdapterCompositeFactory 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!