bridge или все таки не мост
От: sapunidze Россия  
Дата: 10.11.03 14:15
Оценка:
Имеется абстрактный класс Document, его необходимо отобразить в виде некой абстрактной формы, скажем, DocumentForm. Document имеет два конкретных воплощения — входящий документ (InDocument) и исходящий документ (OutDocument). Отображаться необходимо на InDocumentForm и OutDocumentForm, соответственно.
Насколько я понял, идея отрыва абстракции от реализации заключается в том числе и в том, что про связь между ними знает только абстракция (причем "абстрактная" абстракция, т.е. базовый класс). Потомки же используют декларированные методы в базовом классе для доступа к фактической реализации (т.е. сами они про реализацию не в курсе).
Если предыдущий абзац не заблуждение, возникает следующий вопрос.
Допустим, я трактую как абстракцию — DocumentForm, а в качестве "утонченной" абстракции — InDocumentForm, реализация — Document, конкретная реализация — InDocument.
Как мне быть с тем, что InDocument имеет дополнительные поля, соответственно методы для доступа к ним, которых нет в Document? (Либо DocumentForm, либо InDocumentForm должен знать про InDocument)
Помогите разобраться, целесообразно ли использовать в данном случае шаблон мост? И как следует поступать если наследники не только конкретизируют базовый класс но и расширяют его функциональность (дело попахивает dynamic_cast<>)

з.ы.
class Document{
...
Load() { LoadFromDB() }
Save() { SaveToDB() }
...
}

class DocumentForm{
...
DocumentForm(int id) { document = new Document(id) }
OnShow() { document->Load() ... }
OnButtonSaveClick { document->Save() }
...
}
Re: bridge или все таки не мост
От: Mishka Норвегия  
Дата: 10.11.03 15:08
Оценка: 6 (1)
Здравствуйте, sapunidze,

Прикинул я тут, схемку UML наваял и вот что получил: у тебя там два моста будет.

// это код на С# 
class Document{}

class InDocumnet : Document{}
class OutDocumnet : Document{}

class InDocumnetBridge
{
  private InDocumnet realDocument;
}

class OutDocumnetBridge
{
  private OutDocumnet realDocument;
}

class InDocumnetForm : InDocumnetBridge{}
class OutDocumnetForm : OutDocumnetBridge{}


Помогло?
Re[2]: bridge или все таки не мост
От: sapunidze Россия  
Дата: 10.11.03 21:44
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Прикинул я тут, схемку UML наваял и вот что получил: у тебя там два моста будет.


...пропуск...

честно говоря не очень понимаю что дает введение данных классов...
Re: bridge или все таки не мост
От: Nicht Россия  
Дата: 11.11.03 08:04
Оценка:
Здравствуйте, sapunidze, Вы писали:

S>Имеется абстрактный класс Document, его необходимо отобразить в виде некой абстрактной формы, скажем, DocumentForm. Document имеет два конкретных воплощения — входящий документ (InDocument) и исходящий документ (OutDocument). Отображаться необходимо на InDocumentForm и OutDocumentForm, соответственно.

S>Насколько я понял, идея отрыва абстракции от реализации заключается в том числе и в том, что про связь между ними знает только абстракция (причем "абстрактная" абстракция, т.е. базовый класс). Потомки же используют декларированные методы в базовом классе для доступа к фактической реализации (т.е. сами они про реализацию не в курсе).
S>Если предыдущий абзац не заблуждение, возникает следующий вопрос.
S>Допустим, я трактую как абстракцию — DocumentForm, а в качестве "утонченной" абстракции — InDocumentForm, реализация — Document, конкретная реализация — InDocument.
S>Как мне быть с тем, что InDocument имеет дополнительные поля, соответственно методы для доступа к ним, которых нет в Document? (Либо DocumentForm, либо InDocumentForm должен знать про InDocument)
S>Помогите разобраться, целесообразно ли использовать в данном случае шаблон мост? И как следует поступать если наследники не только конкретизируют базовый класс но и расширяют его функциональность (дело попахивает dynamic_cast<>)

S>з.ы.

S>class Document{
S>...
S> Load() { LoadFromDB() }
S> Save() { SaveToDB() }
S>...
S>}

S>class DocumentForm{

S>...
S> DocumentForm(int id) { document = new Document(id) }
S> OnShow() { document->Load() ... }
S> OnButtonSaveClick { document->Save() }
S>...
S>}

Мне тут не очень понятен один аспект.
Если у тебя OutDocument отображается в OutDocumentForm, а InDocument в InDocumentForm, то есть ли смысл засовывать в каждую из форм Document. Пусть каждая из них работает со своим подклассом Document. И никакого динамиккаста не будет.
Или в этом есть какой — то потаенный смысл?
Re[3]: bridge или все таки не мост
От: Mishka Норвегия  
Дата: 11.11.03 09:50
Оценка:
Здравствуйте, sapunidze, Вы писали:

S>честно говоря не очень понимаю что дает введение данных классов...


Что ты хотел

Например, у тебя есть документ "счёт-фактура" и ты хочешь отобразить его как входящий документ, тогда тебе надо сделать следующее:


class Invoice : InDocumentBridge
{
  OnShow(){this.realDocument.Load();...}
  OnButtonSaveClick{this.realDocument.Save();...}
}


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

class Document{}
class InDocumnet : Document{}
class Invoice : InDocumnet{}


а затем у тебя есть три возможности:

1. Решение в лоб
class InvoiceForm
{
  OnShow(){this.document.Load();...}
  OnButtonSaveClick{this.document.Save();...}
  private Invoice document;
}


2. Здесь ты как раз должен будешь пользовать dynamic_cast
class Form
{
  OnShow(){this.document.Load();...}
  OnButtonSaveClick{this.document.Save();...}
  private Document document;
}
class InvoiceForm : Form
{
  MyFunc(){Invoice invoice = (Invoice)document;...}
}


3. Дизайнерский финт Или, если интересно, шаблон GoF "Template Method".
abstract class Form
{
  OnShow(){this.getDocument().Load();...}
  OnButtonSaveClick{this.getDocument().Save();...}
  abstract protected Document getDocument();
}
class InvoiceForm : Form
{
  protected Document getDocument(){return document;}
  private Invoice document;
}


Третий вариант с моей точки зрения самый лучший.
Re[2]: bridge или все таки не мост
От: sapunidze Россия  
Дата: 11.11.03 12:38
Оценка:
Здравствуйте, Nicht, Вы писали:

N>Мне тут не очень понятен один аспект.

N>Если у тебя OutDocument отображается в OutDocumentForm, а InDocument в InDocumentForm, то есть ли смысл засовывать в каждую из форм Document. Пусть каждая из них работает со своим подклассом Document. И никакого динамиккаста не будет.
N>Или в этом есть какой — то потаенный смысл?

дело в том, что Document и DocumentForm — не "пустые" абстрактные классы. там реализована логика общая для обоих типов документов. соответственно на предлагаемое усложнение (переходя от статического связывания к динамическому) я пошел дабы избавиться от необходимости реализовывать одинаковую функциональность в двух парах In-InForm Out-OutForm.

в принципе, я допускаю, что в данном случае стоит задуматься о необходимости использования паттерна мост.
но другого паттерна в альтернативу я предложить не могу.
Re[4]: bridge или все таки не мост
От: sapunidze Россия  
Дата: 11.11.03 13:06
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, sapunidze, Вы писали:


S>>честно говоря не очень понимаю что дает введение данных классов...


M>Что ты хотел


Исхитрись-ка мне добыть
То-Чаво-Не-Может-Быть!
Запиши себе названье,
Чтобы в спешке не забыть! (с) Филатов

...другие варианты пропустил... (в виду того, что от этого наоборот уйти хотелось)

M>3. Дизайнерский финт Или, если интересно, шаблон GoF "Template Method".

M>
M>abstract class Form
M>{
M>  OnShow(){this.getDocument().Load();...}
M>  OnButtonSaveClick{this.getDocument().Save();...}
M>  abstract protected Document getDocument();
M>}
M>class InvoiceForm : Form
M>{
M>  protected Document getDocument(){return document;}
M>  private Invoice document;
M>}
M>


M>Третий вариант с моей точки зрения самый лучший.


Не печалься и не хнычь!
Стоит только кинуть клич!
Ну-ко станьте предо мною,
Тит Кузьмич и Фрол Фомич! () туда же...

спасибо
Re[4]: bridge или все таки не мост
От: sapunidze Россия  
Дата: 12.11.03 07:05
Оценка:
Здравствуйте, Mishka, Вы писали:


M>3. Дизайнерский финт Или, если интересно, шаблон GoF "Template Method".

M>
M>abstract class Form
M>{
M>  OnShow(){this.getDocument().Load();...}
M>  OnButtonSaveClick{this.getDocument().Save();...}
M>  abstract protected Document getDocument();
M>}
M>class InvoiceForm : Form
M>{
M>  protected Document getDocument(){return document;}
M>  private Invoice document;
M>}
M>


(теоретический интерес )
а не является ли getDocument() "вырожденным" примером реализации Factory Method?
или все таки раз нет порождения, знамо...?
Re[3]: bridge или все таки не мост
От: Nicht Россия  
Дата: 12.11.03 08:21
Оценка:
Здравствуйте, sapunidze, Вы писали:

S>дело в том, что Document и DocumentForm — не "пустые" абстрактные классы. там реализована логика общая для обоих типов документов. соответственно на предлагаемое усложнение (переходя от статического связывания к динамическому) я пошел дабы избавиться от необходимости реализовывать одинаковую функциональность в двух парах In-InForm Out-OutForm.


S>в принципе, я допускаю, что в данном случае стоит задуматься о необходимости использования паттерна мост.

S>но другого паттерна в альтернативу я предложить не могу.

На сколько мне известно, мост применяется когда нужно свести несколько одинаковых функциональностей с разным интерфейсом к одному интерфейсу.
Как я понял InDocument и OutDocument значительно отличаются по своим функциям. Так что скорее всего мост в чистом виде не подойдет.
Но можно попробовать придумать что — то типа загдушки. Для каждого вида документа своя. В конструктор этой заглушки подавать непосредственно определенный вид документа(ну или в самом документе определить метод, который бы ее выдавал) А на основе этой заглушки создавать уже DocumentForm, И все методы, которые новые, делегировать этой заглушке. В общем это очень на мост похоже.

Что — то типа этого:


public class DocumentGag
{
   private Document doc;

   public DocumentGag ( Document doc )
   {
      this.doc = doc;
   }
   
   public Document getDocument ()
   {
      return doc;
   }
}

public abstract class Document
{
    public void write()
    {
       //TODO:
    }
}

public abstract class DocumentForm
{
    private Document doc;

    public DocumentForm ( Document doc )
    {
        this.doc = doc;
    }

    public writeDocument ()
    {
        doc.write();
    }
}

public class InDocument extends Document
{    
    public void superInWrite ()
    {
        //TODO SUPER:
    }
}

public class InDocumentGag extends DocumentGag
{
     private InDocument doc;
     public InDocumentGag ( InDocument doc )
     {
          super ( doc );
          this.doc = doc;
     }
     
     public void superInWrite ()
     {
         doc.superInWrite();
     }
}

public class InDocumentForm extends DocumentForm
{
   private InDocumentGag gag;

   public InDocumentForm ( InDocumentGag gag )
   {
       super( gag.getDocument() );
       this.gag = gag;
   }

   public void superWriteDocument ()
   {
       gag.superInWrite();
   }
}


тоже самое и для Out.
Тут конечно есть свои недостатки. Например дублирование ссылки на документ.
Re[5]: bridge или все таки не мост
От: Mishka Норвегия  
Дата: 12.11.03 09:13
Оценка:
Здравствуйте, sapunidze, Вы писали:

S>(теоретический интерес )

S>а не является ли getDocument() "вырожденным" примером реализации Factory Method?
S>или все таки раз нет порождения, знамо...?

Если совсем по науке, то нет. Этот метод не создаёт объекты классов, то есть и сам шаблон не является "порождающим".
Это точно Template Method, если читать функциональность этого класса следующим образом:
есть алгоритм, состоящий из двух шагов. Первый — получить документ, второй — сохранить его. Первый шаг может изменятся в зависимости от документа, потому следует поручить этот шаг подклассам.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.