【问题标题】:Does decorator pattern need concrete class? (and to call base class from decorator?)装饰器模式需要具体的类吗? (并从装饰器调用基类?)
【发布时间】:2023-03-13 06:28:01
【问题描述】:

这是来自: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(){}    
      }    
    }

现在与这个比较(来自 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());
    }
  }

几个问题, 简单的一个: 1.具体装饰器(如第一个示例)是否必须调用基类? 2. 在第二个例子中根本没有具体的组件,似乎只有一个组件和装饰器,仅此而已,对吗?还是装饰器模式吗?对我来说似乎是这样。只是想澄清一些事情。

谢谢

【问题讨论】:

    标签: design-patterns decorator


    【解决方案1】:
    1. 是的,它调用基类来执行基本的Operation方法。这样做,装饰器会添加一个行为。
    2. 是的,它仍然是一个装饰器

    您可以编写设计模式的各种实现,重要的是要满足意图,在这种情况下,“动态地将附加职责附加到对象”并且您在 C# 中编写了 N 种方式中的 2 种。

    HTH

    【讨论】:

    • 我唯一的另一个问题是,为什么另一个例子没有调用基类?
    • 调用photo实例的Drawer方法,photo是构造函数中传入的base实例,所以是一样的。
    猜你喜欢
    • 2019-01-18
    • 1970-01-01
    • 2020-11-24
    • 1970-01-01
    • 2016-08-18
    • 2014-01-14
    • 1970-01-01
    • 2019-10-13
    • 2020-01-11
    相关资源
    最近更新 更多