开发者

Which design pattern does this?

开发者 https://www.devze.com 2022-12-19 03:54 出处:网络
I have a small question regarding design patterns I have this 2 classes which extend from the very same class (doctrine_record) so they mainly have the very same methods and functions however, they n

I have a small question regarding design patterns

I have this 2 classes which extend from the very same class (doctrine_record) so they mainly have the very same methods and functions however, they now have different attributes. I'd like to create a wrapper that exposes the 2 classes summed attributes, I remember there was a pattern for this but I've been looking through the book and just couldn't find it. What I'm basically trying to do is map attributes, however since each of these classes store their data on different tables I'd have to frequently invoke the same method (save()) for each, since there are going to be plenty of classes which I'm some how going to marry I don't want to have to write the whole code for each pair of classes I have. Do you have any suggestion on how can I archive this?

To make myself more clear I'll add a simple example

I have these 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;
}

as you can see, 1 Content can have N Content_translations , since it's becoming a very repetitive task to work with the specific translation I need for a certain content I'd like to merge this 2 classes, avoiding modifying an开发者_StackOverflowy of the 2.

I'm trying to have a class which I tell (better if at runtime) the 2 classes I have and it merge em so if I instance a certain content (lets call this new class sections) it'd have both classes attributes. and if I call the save() method I'd have to call it on both objects, I remember that there is a pattern like this, but I just can't remember de name of it.

What I'm basically trying to do here is the following, let's say I instance a Section (which's class is the class I'm trying to create)

so if I do this, I'd get my content and the corresponding translation in english, and I can even access the attributes of both

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

and if I modify any of them and call the save() method

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

this would invoke the save() method on each of my 2 contained classes (content and content_translations) so the info is store on 2 different tables, now if I do this

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

this would only alter the content_translations object sin I instanced the 'es' version of my object

Hope you can help me :) and thanks in advance


There isn't really a design pattern for this - you just have to use your analytic skills on this one.

If you have the same methods but different fields, I would use a Hashtable called attributes. You can check for the existence of the attribute. One of the attributes could be type to differentiate between them.

If there are only a few types, you could potentially multiclass, but it would seem like overclassing if you wanted to add more than, say, 10.


To solve your problem I count three design patterns: Adapter, Composite, Factory Method.

I propose solution something like that:

///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();
  }
}

Usage:

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!
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号