views:

139

answers:

1

This is an example from: dofactory

I reformatted it a bit for better fit (compressed):

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(){}    
      }    
    }

Now compare with this one (which is from C# Design patterns 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());
    }
  }

Couple of questions, easy one: 1. Does the concrete decorator (as in the first example) have to call base class? 2. In the second example there is no concrete component at all, it seems that there's only a component and decorators, that's all, am I right? Is it still decorator pattern? It's seems like it is to me. Just wanted to clear some things up.

Thanks

A: 
  1. Yes, it calls the base class to execute the base Operation method. Doing this the decorator adds a behaviour.
  2. Yes, it's still a decorator

You can write various implementation of a design pattern, the important thing is to satisfy the intent, in this case "Attach additional responsibilities to an object dynamically" and you write 2 of the N way to do this in C#.

HTH

ema
my only other question would be, how come the other example is not calling base class?
ra170
It calls the Drawer method of the photo instance, and photo is the base instance passed in the constructor, so it's the same.
ema