Wir verwenden derzeit das Decorator-Entwurfsmuster, um Caching durchzuführen. So haben wir eine Reihe von Klassen, die wie folgt aussehen:Ein Problem bei der Verwendung des Decorator-Entwurfsmusters
interface IComponent
{
object Operation();
object AnotherOperation();
}
public ConcreteComponentA : IComponent
{
public object Operation()
{
return new object();
}
public object AnotherOperation()
{
return new object();
}
}
public ConcreteDecoratorA : IComponent
{
protected IComponent component;
public object Operation()
{
if(!this.cache.Contains("key")
{
this.cache["key"] = this.component.Operation();
}
return this.cache["key"];
}
Also, wenn ein Client-Caching verwenden wollten, sie würden erstellen Sie eine neue ConcreteDecoratorA und passieren in einem ConcreteComponentA an den Konstruktor. Das Problem, vor dem wir stehen, ist, stellen Sie sich vor, dass AnotherOperation() einen Aufruf zur Operation benötigt, um seine Arbeit zu erledigen. ConcreteComponentA könnte nun wie folgt aussehen:
public ConcreteComponentA : IComponent
{
public object Operation()
{
return new object();
}
public object AnotherOperation()
{
object a = this.Operation();
// Do some other work
return a;
}
}
Das Problem, das ist, wenn Betrieb() Methode aus AnotherOperation() -Methode aufrufen, wird der Dekorateur Implementierung nie genannt werden, weil offensichtlich der Dekorateur nicht in der Vererbungshierarchie ist von ConcreteComponentA.
Haben wir irgendwo eine schlechte Designentscheidung getroffen oder ist dies nur eine Einschränkung des Dekorationsdesignmusters, das wir akzeptieren müssen?
Beachten Sie, dass in meinem realen Beispiel ConcreteComponentA ein Wrapper für ein Drittanbietersystem ist, über das wir keine Kontrolle haben. Wir haben IComponent und eine Reihe von POCOs entwickelt, mit denen wir dieses Drittanbietersystem abstrahieren. In diesem Fall müssen wir zwei Aufrufe an ihr System machen, um die benötigten Daten zu erhalten, es geht nur darum, wo wir diese beiden Anrufe tätigen.
Haben Sie keine Kontrolle über ConcreteComponentA oder das Drittanbietersystem, das von ConcreteComponentA umschlossen wird? – dtb
Ja, ConcreteComponentA ist eine unserer Klassen. Aufgrund von Politik, Budget usw. ist es schwierig und äußerst unwahrscheinlich, dass Dinge in einem Drittparteisystem geändert werden. Daher definiert IComponent eine einzelne Operation, die wir verwenden möchten, aber aufgrund der Struktur ihres Service müssen wir mehrere Aufrufe innerhalb dieser einzigen Operation in ConcreteComponentA durchführen. –