Нужен ли шаблону декоратора конкретный класс? (и вызывать базовый класс из декоратора?)

Это пример из: dofactory

Я немного переформатировал его для лучшего соответствия (сжатый):

namespace DoFactory.GangOfFour.Decorator.Structural{
class MainApp{

        static void Main(){   
          ConcreteComponent c = new ConcreteComponent();   
          ConcreteDecoratorA d1 = new ConcreteDecoratorA();    
          ConcreteDecoratorB d2 = new ConcreteDecoratorB();

          d1.SetComponent(c);    
          d2.SetComponent(d1);   
          d2.Operation();  
        }    
      }

      abstract class Component{    
        public abstract void Operation();    
      }

      class ConcreteComponent : Component{    
        public override void Operation(){    
          Console.WriteLine("ConcreteComponent.Operation()");    
        }    
      }    

      abstract class Decorator : Component{    
        protected Component component;    

        public void SetComponent(Component component){    
          this.component = component;   
        }    

        public override void Operation(){    
          if (component != null){    
            component.Operation();    
          }    
        }    
      }     

      class ConcreteDecoratorA : Decorator{    
        public override void Operation(){    
          ****base.Operation();****    
          Console.WriteLine("ConcreteDecoratorA.Operation()");    
        }    
      }   

      class ConcreteDecoratorB : Decorator{    
        public override void Operation(){    
          **base.Operation();**    
          AddedBehavior();    
          Console.WriteLine("ConcreteDecoratorB.Operation()");   
        }    
        void AddedBehavior(){}    
      }    
    }

Теперь сравните с этим (из шаблонов дизайна С# 3.0 - O'reilly):

namespace Given {   

      public class Photo : Form{
      Image image;
      public Photo () {
        image = new Bitmap("jug.jpg");
        this.Text = "Lemonade";
        this.Paint += new PaintEventHandler(Drawer);
      }

      public virtual void Drawer(Object source, PaintEventArgs e) {
        e.Graphics.DrawImage(image,30,20);
      }

      private void InitializeComponent(){
          this.SuspendLayout();
         this.ClientSize = new System.Drawing.Size(283, 250);
          this.Name = "Photo";
          this.ResumeLayout(false);
      }
    }
  }

  class DecoratorPatternExample {

    class BorderedPhoto : Photo {
      Photo photo;
      Color color;

      public BorderedPhoto (Photo p, Color c) {
        photo = p;
        color=c;
      }

      public override void Drawer(Object source, PaintEventArgs e) {
        photo.Drawer(source, e);
        e.Graphics.DrawRectangle(new Pen(color, 10),25,15,215,225);
      }
    }

    class TaggedPhoto : Photo {
       Photo photo;
       string tag;
       int number;
       static int count;
       List <string> tags = new List <string> ();

       public TaggedPhoto(Photo p, string t) {
          photo = p;
          tag = t;
          tags.Add(t);
          number = ++count;
       }

       public override void Drawer(Object source, PaintEventArgs e) {
          photo.Drawer(source,e);
          e.Graphics.DrawString(tag, 
          new Font("Arial", 16), 
          new SolidBrush(Color.Black), 
          new PointF(80,100+number*20));
       }

       public string ListTaggedPhotos() {
          string s = "Tags are: ";
          foreach (string t in tags) s +=t+" ";
          return s;
       }
    }

    static void Main () {    
      Photo photo;
      TaggedPhoto foodTaggedPhoto, colorTaggedPhoto, tag;
      BorderedPhoto composition;

      photo = new Photo();
      Application.Run(photo);
      foodTaggedPhoto = new TaggedPhoto (photo,"Food");
      colorTaggedPhoto = new TaggedPhoto (foodTaggedPhoto,"Yellow");
      composition = new BorderedPhoto(colorTaggedPhoto, Color.Blue);
      Application.Run(composition);
      Console.WriteLine(colorTaggedPhoto.ListTaggedPhotos());

      photo = new Photo();
      tag = new TaggedPhoto (photo,"Jug");
      composition = new BorderedPhoto(tag, Color.Yellow);
      Application.Run(composition);
      Console.WriteLine(tag.ListTaggedPhotos());
    }
  }

Пара простых вопросов: 1. Должен ли конкретный декоратор (как в первом примере) вызывать базовый класс? 2. Во втором примере вообще нет конкретного компонента, кажется, что есть только компонент и декораторы, и все, я прав? Это все еще шаблон декоратора? Это мне кажется. Просто хотел прояснить некоторые вещи.

Спасибо


person ra170    schedule 27.08.2009    source источник


Ответы (1)


  1. Да, он вызывает базовый класс для выполнения базового метода Operation. Делая это, декоратор добавляет поведение.
  2. Да, это все еще декоратор

Вы можете написать различную реализацию шаблона проектирования, главное - удовлетворить намерение, в этом случае «динамически прикреплять дополнительные обязанности к объекту», и вы пишете 2 из N способов сделать это на С#.

ХТН

person ema    schedule 27.08.2009
comment
мой единственный другой вопрос: почему другой пример не вызывает базовый класс? - person ra170; 27.08.2009
comment
Он вызывает метод Drawer экземпляра photo, а photo — это базовый экземпляр, передаваемый в конструктор, так что это одно и то же. - person ema; 29.08.2009