2013-08-16 23 views
5

Ich brauche Hilfe, lose Kopplung zu verstehen. Wie erstellt man eine Klasse, die die Komposition verwendet, um lose gekoppelt zu sein, wenn ein untergeordnetes Objekt mit seinem übergeordneten Objekt kommunizieren muss? Lassen Sie mich ein Beispiel geben:Lose Kupplung in Zusammensetzung

Wir haben dies:

class A { 
    private: 
     B b; 
    public: 
     void foo(); 
}; 

Wie funktioniert das B-Objekt die Funktion foo() aufrufen, aus seinem Behälter Klasse A? Die offensichtliche Antwort lautet: "Gib einfach einen Zeiger von A auf das B", aber das ist eine enge Kopplung und ein unflexibles Design.

Können Sie bitte geben Sie mir eine einfache Lösung für dieses Problem (in C++ oder Java vorzugsweise) oder bieten Design-Techniken, die mit diesen Arten von Problemen umgehen?

Mein Beispiel aus dem wirklichen Leben kommt von der Entwicklung einer Spiel-Engine für ein JRPG. Ich habe diese Klasse:

class StateMachine 
{ 
    private: 
     std::map<std::string, State*> states; 
     State* curState; 
    public: 
     StateMachine(); 
     ~StateMachine(); 
     void Update(); 
     void Render(); 
     void ChangeCurState(const std::string& stateName); 
     void AddState(const std::string& stateName, State* state); 
}; 

In jedem Spiel Schleife Update() von StateMachine genannt wird, die die Update() Funktion von curState aufruft. Ich möchte curState von der StateMachine Klasse anrufen, aber mit losen Kopplung.

+0

Sie sind gekoppelt sowieso da A enthält B. – doctorlove

+0

Make A eine Observable. Mache B zu einem Beobachter. –

Antwort

6

Sie können mit Hilfe von Schnittstellen entkoppeln.

Erstellen Sie eine Schnittstelle F, die die Methode foo() implementiert und diese an B weiterleitet. Lassen Sie A F implementieren. Jetzt können b foo() auf F aufrufen, ohne zu wissen oder auch die Pflege durch A. implementiert

2

Eine Möglichkeit, die Kopplung in dieser Situation zu reduzieren, besteht darin, Schnittstellen für die Objekte zu definieren, die in der Komposition verwendet werden. Dies stellt sicher, dass Änderungen an ihren Implementierungen nichts kaputt machen, sofern sie die von Ihnen definierte Schnittstelle aufrechterhalten. Wenn Sie für die Zusammensetzung auf Schnittstellen angewiesen sind, werden Sie feststellen, dass Sie Ihre Implementierungen jederzeit ändern können, ohne Ihre anderen Klassen zu unterbrechen.

0

Wenn A B verwendet, dann ist es ok, dass es darin enthalten ist. Das Problem tritt auf, wenn B A benötigt, um richtig zu funktionieren, dann sind beide Objekte gekoppelt. Stattdessen sollten Sie versuchen, nur einige Werte oder Referenzen an B und nicht das gesamte Objekt zu übergeben.

Code Umgestalten wenn Sie unbedingt das Ganze ein Objekt in B. benötigen

0

Vielleicht so etwas wie dieses (Java):

public interface A { 
    void foo(); 
} 

public interface B { 
    ... 
} 

public class BImpl implements B { 
    public B(A a) { ... } 
    ... 
} 

public class AImpl implements A { 
    private B b = new BImpl(this); 
    ... 
} 
0

über Ihr Design Denken. Wie A und B verwandt sind, d.h. wenn B Teil von A ist, dann ist die Zusammensetzung in Ordnung. Im Grunde gibt es nur wenige Möglichkeiten, wie Sie andere Klasse zugreifen können 1. Indem Referenz 2. Zusammensetzung/Inheritance 3. Freund Klasse

1

Angesichts Ihrer Update gebe ich Ihnen eine andere Antwort.

kann ich von vier Optionen denken

  1. Pass eine Instanz von StateMachine in jede State und sich keine Sorgen darüber.Das verbindet sie zwar, aber man könnte argumentieren, dass sie ohnehin eng miteinander verbunden sind.

  2. Wie bereits erwähnt, erstellen Sie eine Schnittstelle, die nur die Methoden StateMachine enthält, die Sie für State sichtbar sein möchten, und übergeben Sie diese in State. Dies ist eine Verbesserung, da Sie jetzt einschränken, was State Ihrer StateMachine-Klasse antun kann.

  3. auch erwähnt, ist die Verwendung von Observer/Observable. Hier würde Ihre State Ereignisse erstellen und sie an alle Beobachter feuern. In diesem Fall müsste Ihr StateMachine alle Ihre State s beobachten und entsprechend reagieren. Dies ist absolut gültig, aber wahrscheinlich ein wenig zu kompliziert, vor allem zu Beginn.

  4. Ein anderer Ansatz ist es, etwas wie eine EventBus zu verwenden, erstellt von der StateMachine und in jede State übergeben. Die State kann Ereignisse auf den Ereignisbus auslösen. Die StateMachine kann Ereignisse auf dem Ereignisbus abhören und entsprechend reagieren. Dies ist eine Vereinfachung des Beobachtermusters.