Strategie (Entwurfsmuster) - LinkFang.de





Strategie (Entwurfsmuster)


Die Strategie (englisch strategy) ist ein Entwurfsmuster aus dem Bereich der Softwareentwicklung. Es gehört zur Kategorie der Verhaltensmuster (englisch behavioral design patterns) und definiert eine Familie austauschbarer Algorithmen.[1] Es ist eines der sogenannten GoF-Muster.

Verwendung

Strategie-Objekte werden ähnlich wie Klassenbibliotheken verwendet. Im Gegensatz dazu handelt es sich jedoch nicht um externe Programmteile, sondern um integrale Bestandteile des eigentlichen Programms, die deshalb als eigene Objekte definiert wurden, damit sie durch andere Algorithmen ausgetauscht werden können.

Meistens wird eine Strategie durch Klassen umgesetzt, die eine bestimmte Schnittstelle implementieren. In Sprachen wie Smalltalk, in denen auch der Programmcode selbst in Objekten abgelegt werden kann, kann eine Strategie aber auch durch solche Code-Objekte realisiert werden.

Die Verwendung von Strategien bietet sich an, wenn

  • viele verwandte Klassen sich nur in ihrem Verhalten unterscheiden.
  • unterschiedliche (austauschbare) Varianten eines Algorithmus benötigt werden.
  • Daten innerhalb eines Algorithmus vor Klienten verborgen werden sollen.
  • verschiedene Verhaltensweisen innerhalb einer Klasse fest integriert sind (meist über Mehrfachverzweigungen), aber
    • die verwendeten Algorithmen wiederverwendet werden sollen bzw.
    • die Klasse flexibler gestaltet werden soll.

UML-Diagramm

Erklärung der Akteure

Die Klasse Strategie definiert nur eine Schnittstelle (interface) für alle unterstützten Algorithmen. Die Implementierung der eigentlichen Algorithmen finden sich erst in den Ableitungen wieder (konkrete Strategie).

Der Kontext hält eine Variable der Schnittstelle Strategie, die mit einer Referenz auf das gewünschte Strategieobjekt belegt ist. Auf diese Weise wird der konkrete Algorithmus über die Schnittstelle eingebunden und kann bei Bedarf selbst zur Laufzeit noch dynamisch gegen eine andere Implementierung ausgetauscht werden.

Vorteile

  • Es wird eine Familie von Algorithmen definiert.
  • Es wird die Auswahl aus verschiedenen Implementierungen ermöglicht und dadurch erhöhen sich die Flexibilität und die Wiederverwendbarkeit.
  • Es können Mehrfachverzweigungen vermieden werden und dies erhöht die Übersicht des Codes.
  • Strategien bieten eine Alternative zur Unterklassenbildung der Kontexte.

Nachteile

  • Klienten müssen die unterschiedlichen Strategien kennen, um zwischen ihnen auswählen und den Kontext initialisieren zu können.
  • Gegenüber der Implementierung der Algorithmen im Kontext entsteht hier ein zusätzlicher Kommunikationsaufwand zwischen Strategie und Kontext.
  • Die Anzahl der Objekte wird erhöht.

Beispiel

Als Beispiel kann ein Steuerberechnungsprogramm dienen, das die Berechnung von Steuersätzen möglichst in Strategie-Objekte auslagern sollte, um einfach länderabhängig konfigurierbar zu sein.

Ein anderes Beispiel wäre die Speicherung eines Dokuments oder einer Grafik in verschiedenen Dateiformaten.

Auch ein Packer, der verschiedene Kompressionsalgorithmen unterstützt, kann mit Hilfe von Strategie implementiert sein. Bei Java wird das Entwurfsmuster zum Beispiel zur Delegierung des Layouts von AWT-Komponenten an entsprechende LayoutManager (BorderLayout, FlowLayout etc.) verwendet.

Weitere Beispiele (außerhalb der OOP-Welt):

Programmbeispiele

Beispiel in C++

#include <iostream>
#include <memory>
 
using namespace std;
 
class Strat {
public:
    virtual void operator()() = 0;
    virtual ~Strat() {}
};
 
class Kontext {
    shared_ptr<Strat> _strat;
public:
    Kontext() : _strat(nullptr) {}
    void setStrategy(shared_ptr<Strat> strat)  { _strat = strat; }
    void strategy()  { if (_strat) (*_strat)(); }
};
 
class Strategy1 : public Strat {
public:
    void operator()() { cout << "Foo\n"; }
};
 
class Strategy2 : public Strat {
public:
    void operator()() { cout << "Bar\n"; }
};
 
class Strategy3 : public Strat {
public:
    void operator()() { cout << "FooBar\n"; }
};
 
 
int main() {
    Kontext k;
 
    k.setStrategy( std::shared_ptr<Strat>(new Strategy1) );
    k.strategy();
 
    k.setStrategy( std::shared_ptr<Strat>(new Strategy2) );
    k.strategy();
 
    k.setStrategy( std::shared_ptr<Strat>(new Strategy3) );
    k.strategy();
}

Java

class Klient {
	public static void main(final String[] ARGS) {
		Kontext k = new Kontext();
		k.setStrategie(new KonkreteStrategieA());
		k.arbeite();	// "Weg A"
		k.setStrategie(new KonkreteStrategieB());
		k.arbeite();	// "Weg B"
	}
}
 
 
class Kontext {
	private Strategie strategie = null;
 
	public void setStrategie(final Strategie STRATEGIE) {
		strategie = STRATEGIE;
	}
 
	public void arbeite() {
		if (strategie != null)
			strategie.algorithmus();
	}
}
 
interface Strategie {
	void algorithmus();
}
 
class KonkreteStrategieA implements Strategie {
	public void algorithmus() {
		System.out.println("Weg A");
	}
}
 
class KonkreteStrategieB implements Strategie {
	public void algorithmus() {
		System.out.println("Weg B");
	}
}

Ruby

class Context
  private
  attr_writer :strategy
 
  public
  def initialize(strategy)
    @strategy = strategy
  end
 
  def execute
      unless @strategy.respond_to?('execute')
        raise NotImplementedError,'Strategie-Objekt antwortet nicht auf die execute-Methode'
      end
      @strategy.execute
  end
end
 
class StrategyA
  def execute
     puts 'Der normale Weg'
  end
end
 
class StrategyB
  def execute
     puts 'Ein anderer Weg'
  end
end
 
class StrategyC
  def execute
     puts 'Noch ein anderer Weg'
  end
end
 
a = Context.new(StrategyA.new)
a.execute
# Der normale Weg
 
b = Context.new(StrategyB.new)
b.execute
# Ein anderer Weg
 
c = Context.new(StrategyC.new)
c.execute
# Noch ein anderer Weg

Python

class Context:
    def __init__(self, strategy):
        self.strategy = strategy
 
    def execute(self, a, b):
        return self.strategy(a, b)
 
 
class AddStrategy:
    def __call__(self, a, b):
        return a + b
 
class SubStrategy:
    def __call__(self, a, b):
        return a - b
 
context = Context(AddStrategy())
print('4 + 3 =', context.execute(4, 3))
# 4 + 3 = 7
 
context.strategy = SubStrategy()
print('4 - 3 =', context.execute(4, 3))
# 4 - 3 = 1

Verwandte Entwurfsmuster

Weblinks

Einzelnachweise

  1. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Entwurfsmuster. 5. Auflage. Addison-Wesley, 1996, ISBN 3-8273-1862-9, S. 373.

Kategorien: Verhaltensmuster (Software) | Viererbande-Entwurfsmuster

Quelle: Wikipedia - http://de.wikipedia.org/wiki/Strategie (Entwurfsmuster) (Vollständige Liste der Autoren des Textes [Versionsgeschichte])    Lizenz: CC-by-sa-3.0

Änderungen: Alle Bilder mit den meisten Bildunterschriften wurden entfernt. Ebenso alle zu nicht-existierenden Artikeln/Kategorien gehenden internen Wikipedia-Links (Bsp. Portal-Links, Redlinks, Bearbeiten-Links). Entfernung von Navigationsframes, Geo & Normdaten, Mediadateien, gesprochene Versionen, z.T. ID&Class-Namen, Style von Div-Containern, Metadaten, Vorlagen, wie lesenwerte Artikel. Ansonsten sind keine Inhaltsänderungen vorgenommen worden. Weiterhin kann es durch die maschinelle Bearbeitung des Inhalts zu Fehlern gerade in der Darstellung kommen. Darum würden wir jeden Besucher unserer Seite darum bitten uns diese Fehler über den Support mittels einer Nachricht mit Link zu melden. Vielen Dank!

Stand der Informationen: August 201& - Wichtiger Hinweis: Da die Inhalte maschinell von Wikipedia übernommen wurden, ist eine manuelle Überprüfung nicht möglich. Somit garantiert LinkFang.de nicht die Richtigkeit und Aktualität der übernommenen Inhalte. Sollten die Informationen mittlerweile fehlerhaft sein, bitten wir Sie darum uns per Support oder E-Mail zu kontaktieren. Wir werden uns dann innerhalb von spätestens 10 Tagen um Ihr Anliegen kümmern. Auch ohne Anliegen erfolgt mindestens alle drei Monate ein Update der gesamten Inhalte.