Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];

Вниз

Вопрос для Cyraxa. Как модифицировать GOF паттерн Visitor   Найти похожие ветки 

 
oxffff ©   (2006-12-14 11:53) [40]


> ЮЮ ©   (14.12.06 10:41) [37]
> Что значит работали с новым типом TSomeType5?
>
> ещё один метод
> procedure SomeType5(obj:TSomeType5);virtual; ? это, по твоему
> работа?
> О обычное наследование разве не решает этих проблем.
>
> а это вообще кошмар с точки зрения высшей степени абстракции
> :)
> procedure SomeType1(obj:TSomeType1);virtual;
> procedure SomeType2(obj:TSomeType2);virtual;
> procedure SomeType3(obj:TSomeType3);virtual;
> procedure SomeType4(obj:TSomeType4);virtual;
>
> Нет ли ссылки на человеческое описание "GOF паттерн Visitor",
>  а то ни смысла, ни проблемы не вижу :(


У нас есть объект разнообразных типов.
Есть посетитель.
Мы хотим добавить разновидности объектов причем старые "посетители" их игнорируют.
А новые посетители обрабатывают.
Без перекомпиляции.


 
ЮЮ ©   (2006-12-15 11:33) [41]


> Возможно вам стоит обратить внимание на книгу "Банды четерых"

Задачу ставишь ты, так что оставь банду в покое :)
А т мне, в свою очередь, сразу хочется порекомндовать учебник русского языка :)

У нас есть объект разнообразных типов.
Как это будет по-русски? С глаголами? Или на пальцах?

Предположим, все-таки, что имелось в виду
У нас есть объекты разнообразных типов.

Есть посетитель.
Это объект с набором бессмыссленных методов
procedure SomeType1(obj:TSomeType1);virtual;
procedure SomeType2(obj:TSomeType2);virtual;
...
procedure SomeTypeN(obj:TSomeTypeN);virtual;
?
И "обрабатывает" он их своими методами SomeTypeN ???

Мы хотим добавить разновидности объектов
Куда добавить? Они где-то перечислены кроме как во чреве SomeType1...SomeTypeN ? Можно ли считать любой класс, кроме N указанных,  новой разновидностью? Почему, если мы их не добавляли?  

причем старые "посетители" их игнорируют
Игнорируют это как? Как они их могут не игнорировать, если у них нет даже метода SomeTypeN+1, чтобы их обработать?


> А новые посетители обрабатывают.

Если "обрабатывать" все-таки вызывать метод  SomeTypeN+1(obj:TSomeTypeN+1) то и "обрабатывай" их наздоровье.

Без перекомпиляции.
Новые типы и новые "посетители" должны ещё и без кода появиться? Но при этом "обрабатываться"?

Поясни ддя начала понятия
 "посетитель игнорирует объект класса TSomeType" и  
 "посетитель обрабатывает объект класса TSomeType"


 
iZEN ©   (2006-12-15 11:44) [42]

Конечно, создать новые интерфейсы:


INewVisitor = interface (IVisitor)
//интерфейс-метка без методов, хотя можно и добавить
end;

INewElement = interface
  procedure Accept(AVisitor :INewVisitor);
end;

Добавляем новый объект.
TNewElement = class(TInterfacedObject, INewElement)
public
  procedure Accept(AVisitor :INewVisitor);
end;
Это так, навскидку. В Delphi не проверял безошибочность компиляции.


 
iZEN ©   (2006-12-15 11:51) [43]

Исправляю:
INewElement = interface (IElement)
 procedure Accept(AVisitor :INewVisitor);
end;


 
iZEN ©   (2006-12-15 11:53) [44]

Класс нового визитёра NewVisitor должен реализовать новый интерфейс INewVisitor, соответственно.


 
oxffff ©   (2006-12-15 13:10) [45]


> ЮЮ ©   (15.12.06 11:33) [41]
>
> > Возможно вам стоит обратить внимание на книгу "Банды четерых"
>
> Задачу ставишь ты, так что оставь банду в покое :)
> А т мне, в свою очередь, сразу хочется порекомндовать учебник
> русского языка :)
>
> У нас есть объект разнообразных типов.
> Как это будет по-русски? С глаголами? Или на пальцах?
>
> Предположим, все-таки, что имелось в виду
> У нас есть объекты разнообразных типов.
>
> Есть посетитель.
> Это объект с набором бессмыссленных методов
> procedure SomeType1(obj:TSomeType1);virtual;
> procedure SomeType2(obj:TSomeType2);virtual;
> ...
> procedure SomeTypeN(obj:TSomeTypeN);virtual;
> ?
> И "обрабатывает" он их своими методами SomeTypeN ???
>
> Мы хотим добавить разновидности объектов
> Куда добавить? Они где-то перечислены кроме как во чреве
> SomeType1...SomeTypeN ? Можно ли считать любой класс, кроме
> N указанных,  новой разновидностью? Почему, если мы их не
> добавляли?  
>
> причем старые "посетители" их игнорируют
> Игнорируют это как? Как они их могут не игнорировать, если
> у них нет даже метода SomeTypeN+1, чтобы их обработать?
>
>
> > А новые посетители обрабатывают.
>
> Если "обрабатывать" все-таки вызывать метод  SomeTypeN+1(obj:
> TSomeTypeN+1) то и "обрабатывай" их наздоровье.
>
> Без перекомпиляции.
> Новые типы и новые "посетители" должны ещё и без кода появиться?
>  Но при этом "обрабатываться"?
>
> Поясни ддя начала понятия
>  "посетитель игнорирует объект класса TSomeType" и  
>  "посетитель обрабатывает объект класса TSomeType"


Я уже написал намеки на решения.
Одно из решений.
Вам надо внимательно посмотреть oxffff ©   (13.12.06 00:57) [30].
Если привязываться к смещению в VTB "Посетителя", то мы ограничиваем
обрабатываемый набор типов.
А что если мы будем использовать индекс динамического метода, как признак обрабатываемого типа.
Поэтому поскольку мы не имеем возможность напрямую вызывать GetDynaMethod, то можем задействовать для этих целей и
Dispatch и DefaultHandler.

Вам теперь понятно?

Что касаемо русского языка. Конечно  я сожалею.


 
oxffff ©   (2006-12-15 13:32) [46]

CONST

 OBJECTTYPE1=1;
 OBJECTTYPE2=2;
 OBJECTTYPE3=3;
 ......

AbstractVisitedObject=class

TinfoBlock=packed record
Id:dword;
Obj:AbstractVisitedObject;
end;

Visitor=class
procedure VititObject1(var InfoBlock);message OBJECTTYPE1;
procedure VititObject2(var InfoBlock);message OBJECTTYPE2;
procedure DefaultHandler(var Message); override;
end;

AbstractVisitedObject=class
procedure accept(visitor:Visitor);virtual;abstract;
end;

procedure ConcreteVisitedObject.accept(visitor:Visitor);
var infoBlock:TinfoBlock
begin
infoBlock.id:=CONST_OBJECT_ID;
infoBlock.obj:=self;
visitor.Dispatch(infoBlock);
end;

Понятна идея?


 
oxffff ©   (2006-12-15 13:39) [47]

Более того "конкретный посетитель" может быть дочерним произвольного класса.


 
ЮЮ ©   (2006-12-16 06:53) [48]


> Я уже написал намеки на решения.
> Одно из решений.
> Вам надо внимательно посмотреть oxffff ©   (13.12.06 00:
> 57) [30].


Нелепо смотреть на решения, не имея конретного описания задачи.
Почему бы не ответить на вопросы в [41], чем отсылать к решению, а точнее - наметкам решния


> Более того "конкретный посетитель" может быть дочерним произвольного
> класса.

а как же accept(visitor:Visitor); ? :)

так же и "конкретный посещаемый обект" может наследоваться от "произвольного"  класса, т.к. все свелось обычноой посылке пользовательского сообщения.

Я просто не возьму в толк смысл этой ветки. Доказать Cyrax-y необходимость построения абстактного ядра, предшествующего верхнему слою компонент? Сведя всё доказетельство к тому, что любой VCL компонент может послать другому VCL компоненту пользовательское сообщение?

Из-за чего сыр-бор? И что GOF паттерн Visitor должен дать?


 
oxffff ©   (2006-12-16 12:13) [49]


> ЮЮ ©   (16.12.06 06:53) [48]
>
> > Я уже написал намеки на решения.
> > Одно из решений.
> > Вам надо внимательно посмотреть oxffff ©   (13.12.06 00:
>
> > 57) [30].
>
>
> Нелепо смотреть на решения, не имея конретного описания
> задачи.
> Почему бы не ответить на вопросы в [41], чем отсылать к
> решению, а точнее - наметкам решния
>
>
> > Более того "конкретный посетитель" может быть дочерним
> произвольного
> > класса.
>
> а как же accept(visitor:Visitor); ? :)
>
> так же и "конкретный посещаемый обект" может наследоваться
> от "произвольного"  класса, т.к. все свелось обычноой посылке
> пользовательского сообщения.
>
> Я просто не возьму в толк смысл этой ветки. Доказать Cyrax-
> y необходимость построения абстактного ядра, предшествующего
> верхнему слою компонент? Сведя всё доказетельство к тому,
>  что любой VCL компонент может послать другому VCL компоненту
> пользовательское сообщение?
>
> Из-за чего сыр-бор? И что GOF паттерн Visitor должен дать?
>


Зачем раскрывать все решения.
Для догадливых надо модифицировать accept(visitor:Tobject); :)
Более того, это один из вариантов решения.

Что касаемо задания.

Расширить функциональность паттерна Visitor так, чтобы можно было

1. Добавлять новые типы объектов для посещения.
2. Делать это без перекомпиляции Legacy кода.


 
ЮЮ ©   (2006-12-16 12:21) [50]

Ладно, продолжай парится здесь в одиночку! Громе горящих от гордости глаз, надо иметь ещё и уши :)


 
oxffff ©   (2006-12-16 12:23) [51]

>ЮЮ ©   (16.12.06 06:53) [48]
>так же и "конкретный посещаемый обект" может наследоваться >от "произвольного"  класса, т.к. все свелось обычноой посылке >пользовательского сообщения.

А подумать?
В данной реализации нельзя.


 
oxffff ©   (2006-12-16 12:26) [52]


> ЮЮ ©   (16.12.06 12:21) [50]
> Ладно, продолжай парится здесь в одиночку! Громе горящих
> от гордости глаз, надо иметь ещё и уши :)


Не судите по себе.  :)


 
iZEN ©   (2006-12-16 14:17) [53]

Код на java:
public class DemoVisit {
public static void main(String[] args) {
 Element[] e = new Element[10];
 for (int i = 0; i < e.length; i++) {
  if (i < 5)
   e[i] = new ConcreteElement();
  else
   e[i] = new NewElement();
 }
 Visitor conreteVisitor = new ConcreteVisitor();
 Visitor newVisitor = new NewVisitor();
 for (int i = 0; i < e.length; i++) {
  try {
   conreteVisitor.visitElement(e[i]);
   newVisitor.visitElement(e[i]);
  } catch (UnsupportedOperationException ex) {
   System.out.println(ex.toString());
  }
 }

}
}

abstract class Element {
public abstract void accept(Visitor visitor) throws RuntimeException;
}

interface Visitor {
void visitElement(Element element);
}

class ConcreteVisitor implements Visitor {
public void visitElement(Element element) {
 element.accept(this);
}
}

class ConcreteElement extends Element {
public void accept(Visitor visitor) {
 System.out.println("Посетитель ConcreteElement: "
   + visitor.getClass().getName());
}
}

class NewVisitor implements Visitor {
public void visitElement(NewElement element) {
 element.accept(this);
}
public void visitElement(Element element) {
 throw new UnsupportedOperationException("NewVisitor: Элемент слишком общий!");
}
}

class NewElement extends Element {
public void accept(NewVisitor visitor) {
 System.out.println("Посетитель NewElement: "
   + visitor.getClass().getName());
}
public void accept(Visitor visitor) {
 throw new UnsupportedOperationException("NewElement: не тот визитёр!");
}
}


Вывод в консоли:
Посетитель ConcreteElement: demovisit.ConcreteVisitor
java.lang.UnsupportedOperationException: NewVisitor: Элемент слишком общий!
Посетитель ConcreteElement: demovisit.ConcreteVisitor
java.lang.UnsupportedOperationException: NewVisitor: Элемент слишком общий!
Посетитель ConcreteElement: demovisit.ConcreteVisitor
java.lang.UnsupportedOperationException: NewVisitor: Элемент слишком общий!
Посетитель ConcreteElement: demovisit.ConcreteVisitor
java.lang.UnsupportedOperationException: NewVisitor: Элемент слишком общий!
Посетитель ConcreteElement: demovisit.ConcreteVisitor
java.lang.UnsupportedOperationException: NewVisitor: Элемент слишком общий!
java.lang.UnsupportedOperationException: NewElement: не тот визитёр!
java.lang.UnsupportedOperationException: NewElement: не тот визитёр!
java.lang.UnsupportedOperationException: NewElement: не тот визитёр!
java.lang.UnsupportedOperationException: NewElement: не тот визитёр!
java.lang.UnsupportedOperationException: NewElement: не тот визитёр!


 
Бурундук ©   (2006-12-16 16:35) [54]

Я тут поизвращался немного на заданную тему.
Визитёр несколько ...  не совсем классический получился, но дело своё знает.
Добавлять новые типы объектов для посещения можно хоть до посинения.


{*************************** Vis.pas ******************************************}

unit Vis;

interface

type
 TVisitor = class;
 TVisitorSpecifierClass = class of TVisitorSpecifier;
 TVisitorSpecifier = class;

 TVisitedObject = TObject;

 {TVisitedObject = class
 public
   procedure Accept(Visitor: TVisitor); virtual; abstract;
 end;}

 TVisitor = class
 private
   FSpecifiers: array of TVisitorSpecifierClass;
 public
   procedure AddSpecifier(Specifier: TVisitorSpecifierClass);
   procedure Visit(Obj: TVisitedObject);
 end;

 TVisitorSpecifier = class
 public
   class function AcceptedClass: TClass; virtual; abstract;
   class procedure Visit(Visitor: TVisitor; Obj: TVisitedObject); virtual; abstract;
 end;

implementation

{---------------------------------- TVisitor ----------------------------------}

procedure TVisitor.AddSpecifier(Specifier: TVisitorSpecifierClass);
var i, pos: Integer;
begin
 pos := Length(FSpecifiers);
 SetLength(FSpecifiers, pos+1);
 FSpecifiers[pos] := Specifier;

 for i := Length(FSpecifiers)-2 downto 0 do
 begin
   if FSpecifiers[i].AcceptedClass.InheritsFrom(
        Specifier.AcceptedClass
      ) then
   begin
     FSpecifiers[pos] := FSpecifiers[i];
     FSpecifiers[i] := Specifier;
     pos := i;
   end;
 end;
end;

procedure TVisitor.Visit(Obj: TVisitedObject);
var i: Integer;
begin
 for i := Length(FSpecifiers)-1 downto 0 do
 begin
   if Obj.InheritsFrom(FSpecifiers[i].AcceptedClass) then
   begin
     FSpecifiers[i].Visit(Self, Obj);
     Exit;
   end;
 end;
end;

end.

{************************** main.pas ******************************************}

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Vis, VisImpl, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Label1: TLabel;
   ListBox1: TListBox;
   procedure FormCreate(Sender: TObject);
 public
   procedure WriteLog(const s: string);
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var visitor: TVisitor;
begin
 WriteLogProc := WriteLog;

 visitor := TVisitor.Create;

 try
   visitor.AddSpecifier(TVisitorFormSpecifier);
   visitor.AddSpecifier(TVisitorControlSpecifier);
   visitor.AddSpecifier(TVisitorLabelSpecifier);

   visitor.Visit(Self);
   visitor.Visit(Label1);
   visitor.Visit(Button1);
 finally

 end;
end;

procedure TForm1.WriteLog(const s: string);
begin
 ListBox1.Items.Add(s);
end;

end.

{****************************** VisImpl ***************************************}

unit VisImpl;

interface

uses
 Classes, Controls, StdCtrls, Forms, Vis;

type

 TVisitorFormSpecifier = class(TVisitorSpecifier)
 public
   class function AcceptedClass: TClass; override;
   class procedure Visit(Visitor: TVisitor; Obj: TVisitedObject); override;
 end;

 TVisitorControlSpecifier = class(TVisitorSpecifier)
 public
   class function AcceptedClass: TClass; override;
   class procedure Visit(Visitor: TVisitor; Obj: TVisitedObject); override;
 end;

 TVisitorLabelSpecifier = class(TVisitorControlSpecifier)
 public
   class function AcceptedClass: TClass; override;
   class procedure Visit(Visitor: TVisitor; Obj: TVisitedObject); override;
 end;

var
 WriteLogProc: procedure (const s: string) of object;

implementation

procedure WriteLog(const s: string);
begin
 if Assigned(WriteLogProc) then WriteLogProc(s);
end;

{------------------------- TVisitorFormSpecifier --------------------------------}

class function TVisitorFormSpecifier.AcceptedClass: TClass;
begin
 Result := TForm;
end;

class procedure TVisitorFormSpecifier.Visit(Visitor: TVisitor; Obj: TVisitedObject);
var f: TForm;
begin
 f := Obj as TForm;
 WriteLog("Visited form " + f.Name);
end;

{------------------------ TVisitorControlSpecifier ------------------------------}

class function TVisitorControlSpecifier.AcceptedClass: TClass;
begin
 Result := TControl;
end;

class procedure TVisitorControlSpecifier.Visit(Visitor: TVisitor; Obj: TObject);
var c: TControl;
begin
 c := Obj as TControl;
 WriteLog("Visited control " + c.Name);
end;

{--------------------------- TVisitorLabelSpecifier -----------------------------}

class function TVisitorLabelSpecifier.AcceptedClass: TClass;
begin
 Result := TLabel;
end;

class procedure TVisitorLabelSpecifier.Visit(Visitor: TVisitor; Obj: TObject);
var L: TLabel;
begin
 L := Obj as TLabel;

 //inherited;
 WriteLog("Visited label " + L.Name);
end;

end.

{******************************************************************************}


 
oxffff ©   (2006-12-16 19:43) [55]

iZEN ©   (16.12.06 14:17) [53]
Бурундук ©   (16.12.06 16:35) [54]

Приятно, что есть люди,которые предлагают какие-то решения.


 
vuk ©   (2006-12-16 20:18) [56]

to oxffff ©   (16.12.06 19:43) [55]:
Дался Вам этот паттерн... Какой-то он не особо полезный... :)


 
iZEN ©   (2006-12-16 20:31) [57]


> vuk ©   (16.12.06 20:18) [56]
>
> to oxffff ©   (16.12.06 19:43) [55]:
> Дался Вам этот паттерн... Какой-то он не особо полезный.
> .. :)

Да уж, какой-то визитёр шарится по объектам. Чё он там находит, интересно?! :))

А вообще, Visitor — это антипаттерн, который нарушает инкапсуляцию.


 
vuk ©   (2006-12-16 21:19) [58]

to iZEN ©   (16.12.06 20:31) [57]:
>Чё он там находит, интересно?!
Не, ну для перебора разнородных объектов и каких-то действий с ними, оно может и подходит. Но другое дело, что такое обычно нужно бывает как раз на однородных объектах.

>А вообще, Visitor — это антипаттерн, который нарушает инкапсуляцию.
Честно говоря, непонятно, где и как, если у объекта ничего кроме публичного интерфейса нет.


 
Kolan ©   (2006-12-16 21:21) [59]

> vuk ©   (16.12.06 21:19)

Имхо цель Визитора добавить метод - так? Так в Делфи есть Хелперы...


 
vuk ©   (2006-12-16 21:37) [60]

to Kolan ©   (16.12.06 21:21) [59]:
>Имхо цель Визитора добавить метод - так?
Не совсем. Цель - сделать операцию без изменения классов (предположим, нет у нас такой возможности). Это не обязательно означает добавление метода. Ну, например, если задача - сохранение/изменение состояния набора разнородных объектов, то Visitor вполне прокатит.


 
Kolan ©   (2006-12-16 21:47) [61]

> сохранение/изменение состояния набора разнородных

О для этого я его и хочу применить, но блин посещаемые объекты - в разных модулях, а они должны знать о посетителе, а он о них и получается Circular refrence....


 
vuk ©   (2006-12-16 22:05) [62]

to Kolan ©   (16.12.06 21:47) [61]:
Честно говоря, мне кжется, что для конкретно этой задачи больше подойдут механизмы сериализации, RTTI и т.п.


 
Kolan ©   (2006-12-16 22:19) [63]

> [62] vuk ©   (16.12.06 22:05)
> to Kolan ©   (16.12.06 21:47) [61]:
> Честно говоря, мне кжется, что для конкретно этой задачи
> больше подойдут механизмы сериализации, RTTI и т.п.

Я хочу не только сохранить, но и показать пользователю. Те мне нужно сделать настройки, прием настраиваемые объекты находятся в разных модулях. И добраться до нетоторых сложно. Пример: Настройки формы(например позиция окна на экране) и настройки порта(сом). Объект ком порта находится за фасадом.

Вот голову ломаю как это сделать, какой паттерн можно использовать. Пробовал Memento - получилось неочень...


 
iZEN ©   (2006-12-16 22:31) [64]


> vuk ©   (16.12.06 21:19) [58]
>
> to iZEN ©   (16.12.06 20:31) [57]:
> >Чё он там находит, интересно?!
> Не, ну для перебора разнородных объектов и каких-то действий
> с ними, оно может и подходит. Но другое дело, что такое
> обычно нужно бывает как раз на однородных объектах.

Visitor часто используется в паттерне Composite (Композиция).


 
vuk ©   (2006-12-16 22:56) [65]

to Kolan ©   (16.12.06 22:19) [63]:
>Те мне нужно сделать настройки, прием настраиваемые объекты находятся
>в разных модулях
На мой взгляд, если хочется сохранения состояния без привязки к механизмам типа RTTI, то это должен делать сам объект. Как вариант - абстрактное хранилище + методы сохранения загрузки состояния из хранилища. Примерно, как сохраняются непубликованные свойства компонентов в VCL, там есть TFiler и методы DefineProperties.


 
Kolan ©   (2006-12-16 23:20) [66]

> [65] vuk ©   (16.12.06 22:56)
> to Kolan ©   (16.12.06 22:19) [63]:
> >Те мне нужно сделать настройки, прием настраиваемые объекты
> находятся
> >в разных модулях
> На мой взгляд, если хочется сохранения состояния без привязки
> к механизмам типа RTTI, то это должен делать сам объект.
> Как вариант - абстрактное хранилище + методы сохранения
> загрузки состояния из хранилища. Примерно, как сохраняются
> непубликованные свойства компонентов в VCL, там есть TFiler
> и методы DefineProperties.

А как его взять и отобразить? Например нужно чтобы пользователь менял номер порта?


 
vuk ©   (2006-12-16 23:32) [67]

to Kolan ©   (16.12.06 23:20) [66]:
>А как его взять и отобразить? Например нужно чтобы пользователь менял
>номер порта?
Это уже совсем другая задача. В этом случае нужно не просто задавать имена и текущие значения свойств, определяющих состояние, но и как-то определять какого типа эти свойства, задавать диапазон возможных значений, проверять их и т.д.


 
Kolan ©   (2006-12-16 23:52) [68]

> проверять их и т.д.

Во-во а ка это сделать? Я ветку завиду :)


 
Cyrax ©   (2006-12-18 22:25) [69]

Ну так проблему решили или нет ?


 
ЮЮ ©   (2006-12-19 12:27) [70]


> Cyrax ©   (18.12.06 22:25) [69]
> Ну так проблему решили или нет ?


Решать разве не ты должен? По крайней мере, по мнению автора ветки :)


 
oxffff ©   (2006-12-19 13:33) [71]


> Cyrax ©   (18.12.06 22:25) [69]
> Ну так проблему решили или нет ?


Почитай

oxffff ©   [11]
oxffff ©   [29]

А где твое решение?


 
Бурундук ©   (2006-12-19 16:53) [72]

Подумал я на досуге (воскресенье нерабочее выдалось)
над паттерном визитор.

И вот какие мысли мне на счет него пришли:
Визитор на самом деле может служить двум совсем разным целям.

1) Перебор элементов сложной иерархической системы.
Классический пример такого визитора -
TComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
Тут визитор - просто ф-я Proc, выполняющаяся для всех элеметов.
Полезен просто вследствие сложности ручного перебора всех элементов
(или вследствие необходимости обрабатывать не все элементы).
При этом элементы вполне могут вести себя полиморфно (а могут и не вести).
Родственный паттерн - итератор.
Не нужны ни Accept, ни перегруженные Visit-ы

2) Постоянная необходимость добавлять в классы элементов
новые виртуальные функции. Вот тут-то и возникает необходимость
в этих довольно неприятно выглядящих
 TVisitor.Visit(Element: TElement1); virtuel; override;
 TVisitor.Visit(Element: TElement2); virtuel; override;
 TVisitor.Visit(Element: TElement3); virtuel; override;
(а так же TElement.Accept(Visitor: TVisitor))
посколько альтернативой было бы на каждый тип визитора
писать виртуалиьную ф-ю в элементе

 TElement.DoTheSameActionAsVisitor1
 TElement.DoTheSameActionAsVisitor2
 TElement.DoTheSameActionAsVisitor3
 TElement.DoTheSameActionAsVisitor4
 ...
 TElement.DoTheSameActionAsVisitorN

Если таких операций много и их количество постоянно растёт,
а количество классов-наследников TElement можно посчитать
по пальцам левой руки, то тут классический визитор с
Accept-ми и с перегруженными Visit-ами вполне уместен.

Если же ситуации с возможностью неограниченного роста количества
виртуальных функций в элементе нет, то визитор во втором
смысле нафиг не нужен, и более того, вреден.

Но, насколько я понимаю, Вы хотите расширения по типу:  

> Мы хотим добавить разновидности объектов причем старые "посетители"
> их игнорируют.
> А новые посетители обрабатывают.
> Без перекомпиляции.


Переводя на язык виртуальных функций элемента, мы хотим добавить
новую виртуальную функцию в элемент
(каждый новый посетитель соответствует новой виртуальной ф-и),
причём непустая функциональность
будет только у "новых разновидностей" элементов, а у старых она будет пустой.

В дельфи этого эффекта гораздо проще добиться, введя
динамический метод с явным селектором (message метод)
прямо в новый объект:

TNewElement.procedure(var Info); message NEW_OPERATION;
 (или можно подмешать в TNewElement интерфейс INewOperation).

И никаких визиторов (по крайней мере, во втором смысле).


 
oxffff ©   (2006-12-19 17:15) [73]

to Бурундук ©  
Посмотри oxffff [45], [46]


 
Бурундук ©   (2006-12-19 17:21) [74]

oxffff ©   (19.12.06 17:15) [73]
О том и речь.
Не создавать искуственный объект TVisitor,
в который вносить динамические методы по типу элемента,
а внести динамические методы по типу визитора (сиречь операции)
в TElement.
А визитор выбросить. И Accept тоже.



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.65 MB
Время: 0.016 c
15-1165905098
cvg
2006-12-12 09:31
2007.01.07
Есть ли звук громче, чем beep?


15-1166514094
zdm
2006-12-19 10:41
2007.01.07
Windows Vista and BDS 2006


15-1166041883
palva
2006-12-13 23:31
2007.01.07
Изменить соотношение высоты и ширины картинки при просмотре AVI


15-1166125578
AntiUser
2006-12-14 22:46
2007.01.07
Видеофон на основе двух Web-камер


15-1166203353
Mozart
2006-12-15 20:22
2007.01.07
Проблема с "оцифровкой VHS"





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский