Die Ausweitung von beiden Seiten eines Besuchers / Bridge-Muster

stimmen
3

Sagen , dass ich eine Hierarchie von Klassen haben, lassen Sie uns die klassischen verwenden ShapeBeispiele:

abstract class Shape
Circle : Shape
Square : Shape

Ich habe eine zweite Hierarchie von Renderer-Klassen, die die Darstellung von Formen auf unterschiedliche Weise handhaben:

abstract class ShapeRenderer
HtmlShapeRenderer : ShapeRenderer
WindowsFormsShapeRenderer : ShapeRenderer

Variieren diese erlauben würde traditionell unabhängig beinhalten die Brücke Muster. So dass die Rendering - Aktionen ohne Änderung der erweitert werden ShapeKlassen würde bedeuten , traditionell das Besuchermuster.

Jedoch konzentrieren sich beide diese ausschließlich über die Verlängerung , die Umsetzung Seite und nicht die Abstraktion Seite. Sagen wir , ich wollte eine neue hinzufügen Shape, sagen Triangle- ich Rendering der Lage sein wollen, unterstützen Triangleauch. Da sowohl die Besucher und die Brücke Muster stützen sich auf die Abstraktion Hierarchie in eine Reihe von Methoden „Verflachung“, zum Beispiel:

public abstract class ShapeRenderer
{
     public abstract void RenderCircle(Circle c);
     public abstract void RenderSquare(Square s);
}

Der einzige Weg , um das erweitern ShapeHierarchie ist , den Code der Basis zu ändern ShapeRendererKlasse, die eine Bruch Veränderung.

Jon, zu klären: Mit der Brücke oder Besucher erlaubt es die Kunden alternative Rendering - Implementierungen zur Verfügung zu stellen, erfordert aber sie über alle möglichen Formen zu kennen. Was ich möchte in der Lage sein , Kunden zu tun ist , damit auch die Lage, zu verlängern ShapeKlasse und erfordern sie eine Rendering - Implementierung für ihre neue Klasse zu schaffen. Auf diese Weise können bestehende Code arbeiten mit jeder Art von Shape, ohne sich Gedanken über die Einzelheiten von ihnen zu machen.

Gibt es eine gemeinsame Lösung für diese Art von Problem verwendbar in C #?

Veröffentlicht am 09/12/2008 um 18:00
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
2

Wie über die Strategie - Muster ? Wo ist die Strategie ein Verweis auf eine Renderengine Implementierung. Wenn Sie eine neue Form hinzufügen möchten, erstellen Sie eine neue Implementierung der Rendering - Engines , die über die neue Form Implementierung kennen und implementiert die entsprechenden Darstellungsfunktion. Sie fügen eine virtuelle Funktion Form , die als Hilfsfunktion dient dazu, die richtige Form Rendering - Funktion wählen - dh Kreis Objekte rufen die renderCircle () Funktion usw.

In C ++, dass so etwas aussehen könnte:

class Triangle : public Shape
{
  public:
      Triangle( const RenderEngine& whichRenderEngine );
      void render( void ) { renderStrategy->renderTriangle( *this );

  private:
      RenderEngine* renderStrategy;
};

class TriangleRender : HTMLShapeRender
{
   public:
      // if inheriting from concrete class, all other rendering functions 
      // already exist... otherwise re-implement them here.

      void renderTriangle( const Triangle& t ) { /* impl */ }
};

HTMLRenderer r; // doesn't know about Triangles.
Circle c( &r );
c.render();

Square s( &r );
s.render();

// Now we add Triangle
TriangleRenderer tr;
Triangle t( &tr );
t.render();

Square s2( &tr );  // tr still knows how to render squares... 
s2.render();
Beantwortet am 10/12/2008 um 04:50
quelle vom benutzer

stimmen
2

Ich denke , es sollte eine Bruch Änderung sein. Wenn Sie eine Form hinzufügen, klar die bestehenden Renderer werden in der Lage sein zu bewältigen nicht - sie werden geändert werden müssen.

Sie könnten ShapeRenderer ändern RenderTriangle () als virtuelle (nicht abstrakte) Methode hinzufügen, die nur die Tatsache meldet, dass es nicht angemessen wiedergeben kann, und dann fix die Renderer einen nach dem anderen, aber im Grunde sind Sie nicht gehen Lage sein, den neuen Typ ohne mehr Code zu machen.

Welche Art von nicht-unterbrechende Änderung erhoffen Sie wirklich zu erreichen?

Beantwortet am 09/12/2008 um 18:17
quelle vom benutzer

stimmen
1

Meine Lösung wäre hier fast auf jeden Fall eine abstrakte Fabrik zu verwenden, wobei in diesem Fall ein Wörterbuch von ShapeRenderers nach Typ verkeilte laden würde, wobei Typ eine Unterklasse von Shape ist und lassen Sie die Fabrik die ShapeRenderer für jede Form erforderlich liefern (und möglicherweise Plattform, z. B. Fenster, Web, iPhone).

es auf diese Weise tun, bedeutet, dass zu einem Konfigurationsspeicher eine neue Form des Hinzufügen nur eine Änderung erfordern würde, so dass die Fabrik weiß, was mit zur Karte Renderer, was Formen, und eine neue Montag der konkreten Implementierungen enthalten.

Beantwortet am 09/12/2008 um 18:58
quelle vom benutzer

stimmen
1

Entwerfen Sie auf eine Schnittstelle nicht eine Implementierung.

Hey - ich heute zweimal die gleiche Antwort zu verwenden (ich denke, es ist fraglich, dass Renderer ist eine Implementierung) ...

Ich bin mir nicht sicher, ob ich mit der ShapeRenderer Klasse gehen würde. Was ist mit einem IRenderHTML, IRenderWindows, die durch die Formklassen umgesetzt werden?

Sie erhalten Erweiterbarkeit mit den Formen sowie mit den Renderings.

Ich denke, es ist besser OO sein kann, hey Kreis gehen zu sagen, selbst machen, als sich der Kreis zu einer Utility-Klasse zu übergeben für das Rendern. Sie könnten leicht neue Formen und neue Renderings hinzufügen, indem man die Formen des Rendering selbst tun.

Beantwortet am 09/12/2008 um 18:22
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more