Справка Pattern Decorator - PullRequest
       1

Справка Pattern Decorator

1 голос
/ 30 января 2011

Я работаю над примером Орейли

  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;
  using System.Collections.Generic;
  using Given;

  // Decorator Pattern Example                        Judith Bishop  August 2007
  // Draws a single photograph in a window of fixed size
  // Has decorators that are BorderedPhotos and TaggedPhotos that can be composed and added
  // in different combinations

  namespace Given {

    // The original Photo class
    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);
      }
    }
  }

  class DecoratorPatternExample {

    // This simple BorderedPhoto decorator adds a colored BorderedPhoto of fixed size
    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);
      }
    }

    // The TaggedPhoto decorator keeps track of the tag number which gives it 
    // a specific place to be written

    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 () {
      // Application.Run acts as a simple client
      Photo photo;
      TaggedPhoto foodTaggedPhoto, colorTaggedPhoto, tag;
      BorderedPhoto composition;

      // Compose a photo with two TaggedPhotos and a blue BorderedPhoto
      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());

      // Compose a photo with one TaggedPhoto and a yellow BorderedPhoto
      photo = new Photo();
      tag = new TaggedPhoto (photo,"Jug");
      composition = new BorderedPhoto(tag, Color.Yellow);
      Application.Run(composition);
      Console.WriteLine(tag.ListTaggedPhotos());
    }
  }
/* Output

TaggedPhotos are: Food Yellow                                                                                                  
TaggedPhotos are: Food Yellow Jug   
*/

Следующее упражнение

Предположим, что класс Photo был написан с Drawer как обычный (не виртуальный) метод, и это не может быть изменено. Восстановите Пример 2-2, чтобы он работал при этом ограничении

Как я могу это сделать?

Мой подход

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using GivenWihInterface;


namespace GivenWihInterface
{
    interface IPhoto
    {
        void Drawer(object sender, PaintEventArgs e);
    }

    class Photo : Form, IPhoto
    {
        Image image;

        public Photo()
        {
            image = new Bitmap(@"c:\users\anishmarokey\documents\visual studio 2010\Projects\Design_Pattern_Decorator\DecoratorPattern_RealExample\Images\apple-6.jpg");
            this.Text = "Apple";
            this.Paint += new PaintEventHandler(Drawer);
        }
        public void Drawer(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(image, 20, 20);
        }
    }

    class BorderPhoto : Form, IPhoto
    {
        IPhoto pho;
        Color color;

        public BorderPhoto(IPhoto p, Color c)
        {
            pho = p;
            color = c;
            this.Paint += new PaintEventHandler(Drawer);
        }

        public void Drawer(object sender, PaintEventArgs e)
        {
            pho.Drawer(sender, e);
            e.Graphics.DrawRectangle(new Pen(color, 10), 25, 15, 215, 225);
        }
    }
}
namespace DecoratorPattern_RealExample
{
    class DecoratorPatternWithInterface
    {
        static void Dispaly(GivenWihInterface.IPhoto p)
        {
            Application.Run((Form)p);
        }
        static void Main()
        {
            IPhoto component = new GivenWihInterface.Photo();
            Dispaly(component);

            component = new GivenWihInterface.Photo();
            IPhoto p = new GivenWihInterface.BorderPhoto(component,Color.Red);
            Application.Run((Form)p);
        }
    }
}

это правильный путь?

1 Ответ

2 голосов
/ 30 января 2011

Да, это подходящая реализация "декоратора".Единственное, что я хотел бы спросить: нужно ли вам наследовать от Form или достаточно реализации IPhoto.На что можно ответить только с большим контекстом.

Кроме того, жестко запрограммированные (размеры?) Значения выглядят так, как если бы некоторые существующие значения были доступны где-то лучше.

Примерсамо по себе это необычно - вы должны были ввести интерфейс, что в значительной степени является изменением, которого вы пытаетесь избежать;и тип обрабатывает событие на себе , что является плохой практикой.Мне почти интересно, хотят ли они, чтобы вы подключились к конвейеру событий, но на самом деле это не был бы декоратор.

Я подозреваю, что они хотят, чтобы вы кодировали против Form, а не IPhoto, который вы ввели, что позволило быВы должны украсить много вещей.Но вам нужно иметь известный метод для вызова формы, например Paint () - за исключением того, что здесь происходит событие, а не метод, поэтому имя будет другим.И снова мы можем подключить событие, но это не классическое использование декоратора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...