Ihre Intuition ist ziemlich gut, denn Ihre Klassen sind in der Tat sehr eng aneinander gekoppelt. Ich beziehe mich auf Bob Martins Grundsätze des objektorientierten Designs .
Nach der Prinzip der einzigen Verantwortung Sie möchten sicherstellen, dass Sie nicht beide Klassen aktualisieren müssen, wenn sich eine von ihnen ändert. Im Moment wissen beide Klassen ein wenig zu viel übereinander.
Wir können beginnen mit EditMapUtilites
und den Zugriff auf den Sitzungshandler umgestalten, um die Absicht besser zu vermitteln. Vor allem der Anwendungsstatus ist auf den Benutzer beschränkt. Wir können auch ändern, wie wir auf diese Werte zugreifen, um die Kopplung zu verringern, indem wir Methoden verwenden, die das gleiche Ziel erreichen.
public class EditMapUtlities
{
//Omitting the wireup details for now
private SessionHandler ApplicationState {get; set;}
public static Boolean isInitialEditMapPageLoad
{
get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
}
// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}
Und die SessionHandler
Klasse würde nun zwei neue Methoden enthalten:
public static T GetValue<T>(String key)
{
return currentSession[key] ?? default(T);
}
public static void SetValue(String key, Object val)
{
currentSession[key] = val;
}
Ok, eine Klasse ist jetzt etwas ausführlicher, aber Ihre Sitzungsklasse ist einfacher und flexibler. Das Hinzufügen zusätzlicher Werte ist einfach, aber Sie werden sich vielleicht fragen, warum Sie nicht einfach eine reine Sitzung verwenden?
Der Grund für diese Umstrukturierung der Klassen war, dass wir einen Schritt näher an eine saubere Trennung zwischen ihnen herankommen wollten. Durch den Zugriff auf unsere SessionHandler
Klasse über eine Eigenschaft können wir nun einen Schritt weiter gehen und die Prinzip der Inversion von Abhängigkeiten .
Anstatt sich auf eine konkrete Implementierung von SessionHandler
Warum abstrahieren wir nicht die Speicherung von Anwendungsstatusvariablen hinter einer Schnittstelle? Eine, die wie folgt aussieht:
public interface IApplicationState
{
public T GetValue<T>(String key);
public SetValue(String key, Object val);
}
Jetzt können wir einfach unsere Eigenschaft innerhalb von EditMapUtlities
um die Schnittstelle zu verwenden, und übergeben Sie diese durch den Konstruktor unter Verwendung der guten alten manuellen Dependency Injection.
public class EditMapUtlities
{
//Omitting the wireup details for now
private IApplicationState ApplicationState {get; set;}
public EditMapUtilities(IApplicationState appState)
{
if(appState == null) throw new ArgumentNullException("appState");
ApplicationState = appState;
}
public static Boolean isInitialEditMapPageLoad
{
get { return ApplicationState.GetValue<Boolean>("EditMapInitialPageLoad"); }
set { ApplicationState.SetValue("EditMapInitialPageLoad", value); }
}
// REST OF CLASS NOT GERMAIN TO DISCUSSION AND OMITTED
}
Sie können Ihr System leicht überarbeiten SessionHandler
Klasse muss die Schnittstelle implementieren und darf nicht statisch sein:
public SessionHandler: IApplicationState { //Implementation }
Wenn Sie die Abwärtskompatibilität mit anderen Bereichen des Codes aufrechterhalten müssen, können Sie eine Wrapper-Klasse erstellen und SessionHandler statisch lassen:
public SessionHandlerWrapper: IApplicationState
{
//Call SessionHandler from within this class
}
Es stimmt, dass Sie Ihre konkrete Instanz von IApplicationState
und übergibt sie an EditMapUtilities
aber jetzt ist keine der beiden Klassen von der anderen abhängig. Wenn Sie dies in der Zukunft in der Datenbank speichern wollten, müssten Sie einfach eine neue Klasse schreiben, die IApplicationState
. Nur der aufrufende Code müsste geändert werden, um die neue Datenbankklasse anstelle der sitzungsbasierten Klasse zu verwenden.
Jetzt können Sie Ihre neue, lose gekoppelte Architektur und die minimalen Änderungen genießen, die Sie vornehmen müssen, um neue Funktionen hinzuzufügen.