6

Chcę utworzyć klasę, która może korzystać z jednego z czterech algorytmów (a używany algorytm jest znany tylko w czasie wykonywania). Myślałem, że wzór strategii jest odpowiedni, ale moim problemem jest to, że każdy algorytm wymaga nieco innych parametrów. Czy używanie strategii byłoby złym pomysłem, ale przekazanie odpowiednich parametrów do konstruktora ?.Który wzór jest najbardziej odpowiedni?

Oto przykład (dla uproszczenia załóżmy, że istnieją tylko dwie możliwe algorytmy) ...

class Foo 
{ 
private: 
    // At run-time the correct algorithm is used, e.g. a = new Algorithm1(1); 
    AlgorithmInterface* a; 

}; 

class AlgorithmInterface 
{ 
public: 
    virtual void DoSomething() = 0; 
}; 

class Algorithm1 : public AlgorithmInterface 
{ 
public: 
    Algorithm1(int i) : value(i) {} 
    virtual void DoSomething(){ // Does something with int value }; 
    int value; 
}; 

class Algorithm2 : public AlgorithmInterface 
{ 
public: 
    Algorithm2(bool b) : value(b) {} 
    virtual void DoSomething(){ // Do something with bool value }; 
    bool value; 
}; 
+5

Zamiast próbować dopasować kod do jakiegoś założonego schematu, po prostu zaprojektuj go, który jest dla ciebie najwyraźniejszy (i, miejmy nadzieję, najwyraźniejszy dla wszystkich innych) i najłatwiejszy w utrzymaniu. Innymi słowy: wzorce ssania. Jeśli * ty * znalazłeś elegancki sposób rozwiązania problemu, użyj go; To, czy narusza jakiś arbitralny wzorzec projektu, jest nieistotne. – GManNickG

+0

Ponadto, jeśli podasz nam trochę więcej (w jaki sposób przekazywane są te parametry itp.), Możemy dać ci lepszą odpowiedź. Ale tak jak się wydaje, wygląda mi to na świetne rozwiązanie. – GManNickG

Odpowiedz

7

Byłby to poprawny projekt, ponieważ wzór strategia prosi o zdefiniowanie interfejsu i każda klasa, która go implementuje jest prawidłowym kandydatem do uruchomienia kodu strategii, niezależnie od tego, jak jest skonstruowany.

2

myślę, że to poprawne, jeśli wszystkie parametry potrzebne podczas tworzenia nowej strategii a to, co robisz, jest jasne dla wszystkich czytających kod.

0

Można również przekazywać parametry za pomocą pojedynczego interfejsu bloku pamięci zawierającego pary klucz-wartość. W ten sposób interfejs jest wspólny dla wszystkich obecnych i przyszłych algorytmów. Każda implementacja algorytmu wiedziałaby, jak dekodować pary klucz-wartość w swoich parametrach.

+1

Czy nie byłby to przełamanie całej koncepcji wzorca strategii, ponieważ kod wywołujący strategię musiałby wiedzieć, która strategia była używana, aby wiedzieć, które pary klucz/wartość mają zostać przekazane? –

+0

Nie, to tylko wpłynie na implementację klasy Strategii. Zamiast budować algorytmy z unikalnymi interfejsami byłaby to jednolita. Interfejs aplikacji nie powinien się zmieniać. Być może jest to duży koszt w przypadku niewielkiej liczby algorytmów, ale jeśli liczba ta może wzrosnąć do kilkudziesięciu lub więcej, może być łatwiejsza do utrzymania. –

+0

@Eric, myślę, że to zależy od tego, czy oczekujesz, że klienci zawsze dostarczają te same pary kluczy-> wartości. Oczywiście, to by zadać pytanie, dlaczego potrzeba par klucz-> wartość. –

2

Masz rację z tym podejściem. Tak, to jest istotą schematu strategii ... "Zmieniaj algorytm niezależnie od implementacji." Możesz po prostu podać sobie ogólny konstruktor, który przekaże parametry potrzebne do zainicjowania klasy, takie jak tablica obiektów.

Ciesz się!

1

Schemat strategii jest przydatny, gdy użytkownik chce zdecydować, w którym momencie pracy ma być użyty algorytm.

0

IMHO, stoisz przed wyzwaniem, ponieważ wprowadzasz zamieszanie pomiędzy aspektem tworzenia konkretnego algorytmu a rzeczywistym działaniem algorytmu. Dopóki interfejs 'DoSomething' pozostaje taki sam, można użyć Strategy Pattern. To tylko tworzenie różnych konkretnych algorytmów różni się w twoim przypadku, które można obsłużyć za pomocą wzoru projektowego Factory Method.