real_asv ([info]real_asv) wrote,

Продолжение.....

Теперь займемся разработкой класса который будет отвечать за создание экземпляров интерфейса IPainter в зависимости от переданных данных.

Еще раз посмотрим на струкутру XML файла который описывает графические примитивы. Любой объект описывается как

<object type=[тип]>

<[имя свойства]>[значение свойства]</[имя свойства]>

<[имя свойства]>[значение свойства]</[имя свойства]>

……

</object>

 

Нетрудно заметить что любая графическая примитива описывается набором пар имя-значение. В пространстве System.Collections.Specialized имеется достаточно много классов которые могут быть иползованы для такого набора данных. Так как данные хранятся в XML файле, выберем класс NameValueCollection, экземпляры этого класса будут описывать графические примитивы.

Итак, задача класса-фабрики создать экземпляр интерфейса IPainter основываясь на описании объекта NameValueCollection. Посмотрим на код:

      /// <summary>

      /// Represents Factory that responsible for <see cref="IPainter"/> implementation creation.

      /// </summary>

      public class PaintFactory

      {

            /// <summary>

            /// Create implementation of <see cref="IPainter"/> interface.

            /// </summary>

            /// <param name="description">Parameters of graphic primitive.</param>

            /// <returns>implementation of <see cref="IPainter"/> interface.</returns>

            /// <exception cref="ArgumentException">Throws if grphics primitive has invalid parameters.</exception>

            public IPainter GetPainter(NameValueCollection description)

            {

                  IPainter painter=null;

                  switch(description["type"])

                  {

                        case "Circle": int centerX=int.Parse(description["centerX"],CultureInfo.InvariantCulture);

                                        int centerY=int.Parse(description["centerY"],CultureInfo.InvariantCulture);

                                        int radius=int.Parse(description["radius"],CultureInfo.InvariantCulture);

                                        Color color=GetColorFromString(description["color"]);

                                        painter=new Circle(centerX,centerY,radius,color);

                                        break;

                        case "Rectangle": int x=int.Parse(description["x1"],CultureInfo.InvariantCulture);

                                  int y=int.Parse(description["y1"],CultureInfo.InvariantCulture);                                      

                                  int height=int.Parse(description["Height"],CultureInfo.InvariantCulture);                                   

                                  int width=int.Parse(description["Width"],CultureInfo.InvariantCulture);                                     

                                           color=GetColorFromString(description["color"]);

                                           painter=new Rectangle(x,y,width,height,color);

                                           break;

                        default: throw new ArgumentException("Invalid data structure");

 

                  }

                  return painter;

            }

            private Color GetColorFromString(string s)

            {

                  string [] c=s.Split(new char[]{','});

                  int r=int.Parse(c[0],CultureInfo.InvariantCulture);

                  int g=int.Parse(c[1],CultureInfo.InvariantCulture);

                  int b=int.Parse(c[2],CultureInfo.InvariantCulture);

            Color color=Color.FromArgb(r,g,b);

                  return color;

            }

      }

 

Все выглядит достаточно прозрачно, и, я думаю, в пояснениях не нуждается.

Отступление: Класс PaintFactory добавим в сборку Samples.Patterns.SimpleFactorySample.Primitives это единственный класс видный клиентскому приложению(модификатор класса установлен в public).

 

Осталось написать код для клиентского приложения. Он тоже будет достаточно простым:

      public class Painter

      {

            private string _filename;

            private Graphics _graphics;

            private XmlDocument _document=null;

            private XmlElement _root=null;

            /// <summary>

            /// Initializes new instance of <see cref="Painter"/> class.

            /// </summary>

            /// <param name="filename">FileName of XML datasource that contains description of objects.</param>

            /// <param name="graphics">Drawing surface to draw objects.</param>

            public Painter(string filename,Graphics graphics)

            {

                  this._filename=filename;

                  this._graphics=graphics;

                  //Read XML file, initialize _document and _root private fields.

            }

            /// <summary>

            /// Draws graphics objects that are described in the XML datasource.

            /// </summary>

            public void Draw()

            {

                  PaintFactory factory=new PaintFactory();

                  foreach(XmlNode o in this._root.ChildNodes)

                  {

                        NameValueCollection primitive=GetParameters(o);

                        IPainter painter=factory.GetPainter(primitive);

                        painter.Draw(this._graphics);

                  }

          }

        private NameValueCollection GetParameters(XmlNode node)

        {

            NameValueCollection parameters=new NameValueCollection();

            parameters.Add("type",node.Attributes["type"].Value);

                  foreach(XmlNode p in node.ChildNodes)

                  {

                        parameters.Add(p.Name, p.InnerText);

                  }

 

        }

}

 

Клиенсткое приложение вообще ничего не знает о том как устроена та или иная графическая примитива, какие параметры необходимы для ее создания. Приложение выполняет свою основную задачу:

Приложение должно считывать данные из XML файла и отображать описанные примитивы на заданной поверхности(используя класс Graphics).

 

Итак, мы написали простое и легко расширяемое приложения испольую метод Примитивная Фабрика Объектов. Если вдруг появятся другие возможные графические примитивы, мы просто добавим несколько строк кода в сборку Samples.Patterns.SimpleFactorySample.Primitives  и клиентское приложение не будет нуждаться в перекомпилировании.

 

Далее будет преведно еще несколько примеров использования метода Примитивная Фабрика Объектов.

Буквально на днях заработало приложение Планировщик Заданий, типа винодового scheduled tasks в котором я успешно применил этот «паттерн проектирования».


  • Post a new comment

    Error

  • 2 comments

[info]byanich

August 22 2005, 12:42:01 UTC 6 years ago

Сасвем заработался

[info]larisa_ivanovna

October 3 2005, 16:41:17 UTC 6 years ago

а статьи ты пишешь, Сережа?
Create an Account
Forgot your login or password?
Facebook Twitter More login options
English • Español • Deutsch • Русский…