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