Auch bekannt als: Strategie
Strategiemuster ist ein Verhaltensentwurfsmuster, mit dem Sie eine Reihe von Algorithmen definieren und jeden Algorithmus in eine unabhängige Klasse einordnen können, sodass die Objekte des Algorithmus miteinander ersetzt werden können.
FrageEines Tages planen Sie, ein Reiseleiterprogramm für Touristen zu erstellen. Die Kernfunktionalität des Programms besteht darin, schöne Karten bereitzustellen, die den Benutzern eine schnelle Orientierung in jeder Stadt erleichtern. Ein neues Feature der App, auf das sich Nutzer freuen, ist die automatische Routenplanung: Sie möchten eine Adresse eingeben und auf einer Karte den schnellsten Weg zu ihrem Ziel sehen. Die erste Version des Programms kann nur Straßenrouten planen. Autoreisende sind damit sehr zufrieden. Aber natürlich fährt nicht jeder im Urlaub. Deshalb haben Sie in Ihrem nächsten Update die Möglichkeit hinzugefügt, Wanderrouten zu planen. Seitdem haben Sie die Möglichkeit hinzugefügt, Routen für öffentliche Verkehrsmittel zu planen. Und das ist erst der Anfang. Bald planen Sie Routen für Radfahrer. Nach einer Weile müssen Sie erneut Ihre Route planen, um alle Sehenswürdigkeiten der Stadt zu besuchen. Der Leitfadencode wird sehr aufgebläht. Obwohl diese Anwendung aus geschäftlicher Sicht sehr erfolgreich ist, kann ihr technischer Teil Ihnen große Kopfschmerzen bereiten: Jedes Mal, wenn ein neuer Routenplanungsalgorithmus hinzugefügt wird, ändert sich die Größe der Hauptklassen in der Tour Der Guide-Auftrag erhöht sich um das Doppelte. Schließlich haben Sie irgendwann das Gefühl, dass Sie diesen Codehaufen nicht mehr verwalten können. Ob es um die Behebung eines einfachen Fehlers oder die Feinabstimmung von Straßengewichten geht, jede Änderung an einem Algorithmus wirkt sich auf die gesamte Klasse aus und erhöht das Risiko, Fehler in bereits funktionierenden Code einzuführen. Darüber hinaus wird die Teamarbeit ineffizient. Wenn Sie nach erfolgreicher Veröffentlichung der App Teammitglieder rekrutieren, werden diese sich darüber beschweren, dass zu viel Zeit für die Bearbeitung von Zusammenführungskonflikten aufgewendet wird. Bei der Implementierung neuer Funktionen muss Ihr Team dieselbe große Klasse ändern, sodass der von ihnen geschriebene Code möglicherweise miteinander in Konflikt steht. LösungDas Strategiemuster schlägt vor, die Klassen zu identifizieren, die für die Erfüllung einer bestimmten Aufgabe auf viele verschiedene Arten verantwortlich sind, und dann die darin enthaltenen Algorithmen in eine Reihe unabhängiger Klassen, sogenannte Strategien, zu extrahieren Mitte. Die ursprüngliche Klasse namens context muss eine Mitgliedsvariable enthalten, um einen Verweis auf jede Strategie zu speichern. Der Kontext führt die Aufgabe nicht aus, sondern delegiert die Arbeit an das verbundene Richtlinienobjekt. Der Kontext ist nicht für die Auswahl des Algorithmus verantwortlich, der die Anforderungen der Aufgabe erfüllt – der Client übergibt die erforderliche Strategie an den Kontext. Tatsächlich weiß der Kontext nicht viel über die Strategien, er interagiert mit allen Strategien über dieselbe gemeinsame Schnittstelle, die lediglich eine Methode offenlegen muss, um den in der ausgewählten Strategie gekapselten Algorithmus auszulösen. Folglich kann der Kontext unabhängig von bestimmten Strategien sein. Dadurch können Sie neue Algorithmen hinzufügen oder bestehende ändern, ohne den Kontextcode oder andere Strategien zu ändern. Routenplanungsstrategien. In einer Reiseführeranwendung kann jeder Routenplanungsalgorithmus mit nur einerRoutengenerierungsmethode in eine unabhängige Klasse extrahiert werden. Diese Methode empfängt die Start- und Endpunkte als Parameter und gibt eine Sammlung von Routenmittelpunkten zurück. buildRoute
Kontext(Kontext ) verwaltet einen Verweis auf eine bestimmte Richtlinie und kommuniziert mit diesem Objekt nur über die Richtlinienschnittstelle.
Strategy (Strategy)-Schnittstelle ist eine gemeinsame Schnittstelle für alle spezifischen Strategien, die eine Kontextmethode zum Ausführen der Strategie deklariert. Concrete Strategies implementiert verschiedene Variationen des vom Kontext verwendeten Algorithmus.
Wenn ein Kontext einen Algorithmus ausführen muss, ruft er die Ausführungsmethode für sein verbundenes Richtlinienobjekt auf. Der Kontext ist unklar hinsichtlich der Art der beteiligten Strategie und der Art und Weise, wie der Algorithmus ausgeführt wird.
Client (Client) erstellt ein bestimmtes Richtlinienobjekt und übergibt es an den Kontext. Der Kontext stellt einen Setter bereit, damit der Client die zugehörige Richtlinie zur Laufzeit überschreiben kann.
In diesem Beispiel verwendet der Kontext mehrere Strategien , um verschiedene Berechnungen durchzuführen.
// 策略接口声明了某个算法各个不同版本间所共有的操作。上下文会使用该接口来 // 调用有具体策略定义的算法。 interface Strategy is method execute(a, b) // 具体策略会在遵循策略基础接口的情况下实现算法。该接口实现了它们在上下文 // 中的互换性。 class ConcreteStrategyAdd implements Strategy is method execute(a, b) is return a + b class ConcreteStrategySubtract implements Strategy is method execute(a, b) is return a - b class ConcreteStrategyMultiply implements Strategy is method execute(a, b) is return a * b // 上下文定义了客户端关注的接口。 class Context is // 上下文会维护指向某个策略对象的引用。上下文不知晓策略的具体类。上下 // 文必须通过策略接口来与所有策略进行交互。 private strategy: Strategy // 上下文通常会通过构造函数来接收策略对象,同时还提供设置器以便在运行 // 时切换策略。 method setStrategy(Strategy strategy) is this.strategy = strategy // 上下文会将一些工作委派给策略对象,而不是自行实现不同版本的算法。 method executeStrategy(int a, int b) is return strategy.execute(a, b) // 客户端代码会选择具体策略并将其传递给上下文。客户端必须知晓策略之间的差 // 异,才能做出正确的选择。 class ExampleApplication is method main() is 创建上下文对象。 读取第一个数。 读取最后一个数。 从用户输入中读取期望进行的行为。 if (action == addition) then context.setStrategy(new ConcreteStrategyAdd()) if (action == subtraction) then context.setStrategy(new ConcreteStrategySubtract()) if (action == multiplication) then context.setStrategy(new ConcreteStrategyMultiply()) result = context.executeStrategy(First number, Second number) 打印结果。
Wenn Sie verschiedene Algorithmusvarianten im Objekt verwenden möchten und zur Laufzeit zwischen Algorithmen wechseln möchten, können Sie den verwenden Strategiemodus.
Mit dem Strategiemuster können Sie das Objektverhalten zur Laufzeit indirekt ändern, indem Sie es verschiedenen Unterobjekten zuordnen, die bestimmte Unteraufgaben auf unterschiedliche Weise ausführen können.
Verwenden Sie das Strategiemuster, wenn Sie viele ähnliche Klassen haben, die sich nur geringfügig darin unterscheiden, wie sie bestimmte Verhaltensweisen ausführen.
Das Strategiemuster ermöglicht es Ihnen, verschiedene Verhaltensweisen in eine separate Klassenhierarchie zu extrahieren und die ursprünglichen Klassen in derselben zu kombinieren, wodurch doppelter Code reduziert wird.
Wenn der Algorithmus in der Logik des Kontexts nicht besonders wichtig ist, kann die Verwendung dieses Musters die Geschäftslogik der Klasse von ihren Algorithmusimplementierungsdetails isolieren.
Strategiemuster ermöglichen es Ihnen, den Code, interne Daten und Abhängigkeiten verschiedener Algorithmen von anderem Code zu isolieren. Verschiedene Clients können über eine einfache Schnittstelle Algorithmen ausführen und zur Laufzeit umschalten.
Dieses Muster kann verwendet werden, wenn in der Klasse komplexe bedingte Operatoren verwendet werden, um zwischen verschiedenen Varianten desselben Algorithmus zu wechseln.
Strategiemuster extrahiert alle von derselben Schnittstelle geerbten Algorithmen in unabhängige Klassen, sodass bedingte Anweisungen nicht mehr erforderlich sind. Das primitive Objekt implementiert nicht alle Varianten des Algorithmus, sondern delegiert die Ausführung an eines der einzelnen Algorithmusobjekte.
Finden Sie den Algorithmus mit der höheren Änderungshäufigkeit aus der Kontextklasse heraus (kann auch zur Auswahl eines bestimmten Algorithmus verwendet werden). Laufzeit Komplexe bedingte Operatoren für Algorithmusvarianten).
Deklariert eine gemeinsame Strategieschnittstelle für alle Varianten dieses Algorithmus.
Extrahieren Sie die Algorithmen nacheinander in ihre jeweiligen Klassen, und alle müssen die Strategieschnittstelle implementieren.
Fügen Sie eine Mitgliedsvariable in der Kontextklasse hinzu, um einen Verweis auf das Strategieobjekt zu speichern. Stellen Sie dann einen Setter bereit, um die Mitgliedsvariable zu ändern. Der Kontext kann nur über die Richtlinienschnittstelle mit dem Richtlinienobjekt interagieren. Bei Bedarf kann eine Schnittstelle definiert werden, um der Richtlinie den Zugriff auf ihre Daten zu ermöglichen.
Der Client muss die Kontextklasse mit der entsprechenden Richtlinie verknüpfen, damit der Kontext seine Hauptaufgabe in der erwarteten Weise erfüllen kann.
Sie können den Algorithmus innerhalb des Objekts zur Laufzeit wechseln.
Sie können die Implementierung des Algorithmus vom Code isolieren, der den Algorithmus verwendet.
Sie können Zusammensetzung anstelle von Vererbung verwenden.
Öffnungs- und Schließprinzip. Sie können neue Strategien einführen, ohne den Kontext zu ändern.
Wenn sich Ihr Algorithmus selten ändert, gibt es keinen Grund für die Einführung es Neue Klassen und Schnittstellen. Durch die Verwendung dieses Musters wird das Programm nur übermäßig komplex.
Der Kunde muss den Unterschied zwischen Strategien kennen – er muss die geeignete Strategie wählen.
Viele moderne Programmiersprachen unterstützen die Funktionstypfunktion, sodass Sie verschiedene Versionen eines Algorithmus in einer Reihe anonymer Funktionen implementieren können. Auf diese Weise verwenden Sie diese Funktionen genauso wie das Richtlinienobjekt, ohne auf zusätzliche Klassen und Schnittstellen zurückgreifen zu müssen, um Ihren Code einfach zu halten.
Schnittstellen für Bridge-, Stateful- und Strategy-Muster (und in gewissem Maße auch Adapter-Muster) Sehr ähnlich. Tatsächlich basieren sie alle auf dem Kompositionsmuster, das heißt, die Arbeit an andere Objekte zu delegieren, aber jedes löst unterschiedliche Probleme. Muster sind nicht nur Rezepte für die spezifische Organisation von Code; Sie können sie auch verwenden, um die Probleme, die sie lösen, mit anderen Entwicklern zu besprechen.
Befehlsmuster und -strategien sehen ähnlich aus, da beide Objekte mit bestimmten Verhaltensweisen parametrisieren können. Ihre Absichten sind jedoch sehr unterschiedlich.
Sie können Befehle verwenden, um jede Operation in ein Objekt umzuwandeln. Die Parameter der Operation werden zu Mitgliedsvariablen des Objekts. Sie können Transformationen verwenden, um die Ausführung von Vorgängen zu verzögern, Vorgänge in die Warteschlange zu stellen, historische Befehle zu speichern oder Befehle an Remote-Dienste zu senden.
Andererseits können Strategien oft verwendet werden, um verschiedene Wege zum Erreichen einer Sache zu beschreiben, sodass Sie Algorithmen innerhalb derselben Kontextklasse wechseln können.
Im Dekorationsmodus können Sie das Aussehen eines Objekts ändern, während Sie mit Strategien sein Wesen ändern können.
Das Vorlagenmethodenmuster basiert auf dem Vererbungsmechanismus: Es ermöglicht Ihnen, einen Teil des Algorithmus zu ändern, indem Sie einen Teil des Inhalts in der Unterklasse erweitern. Strategien basieren auf einem Kompositionsmechanismus: Sie können einen Teil des Verhaltens eines Objekts ändern, indem Sie unterschiedliche Strategien für das entsprechende Verhalten bereitstellen. Vorlagenmethoden arbeiten auf Klassenebene und sind daher statisch. Richtlinien wirken auf Objektebene und ermöglichen so die Änderung des Verhaltens zur Laufzeit.
Zustände können als Erweiterungen von Strategien betrachtet werden. Beide basieren auf Kompositionsmechanismen: Beide ändern ihr Verhalten in verschiedenen Situationen, indem sie einen Teil der Arbeit an „Hilfsobjekte“ delegieren. Richtlinien machen diese Objekte völlig unabhängig voneinander und sie sind sich der Existenz anderer Objekte nicht bewusst. Das Zustandsmuster schränkt jedoch nicht die Abhängigkeiten zwischen bestimmten Zuständen ein und ermöglicht ihnen, ihren Zustand in verschiedenen Szenarien zu ändern.
Das obige ist der detaillierte Inhalt vonWas ist das Strategiemuster von Java-Designmustern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!