Klasa kontekstu we wzorze strategii

10

Próbuję zrozumieć wzorzec strategii i zadaję sobie pytanie: czy klasa kontekstowa jest niezbędna, czy mogę ją pominąć bez uszczerbku dla celu wzorca?

Miałem wrażenie, że potrzebowałem jakiegoś rodzaju przełącznika do odczytu różnych typów plików, ale nie chciałem po prostu hakować czegoś, a później zajmować się refaktoryzacją (chociaż oczywiście zawsze zdarza się, że kod można refaktoryzować, ale pomysł był taki: spróbuj być jak najbardziej inteligentnym w projekcie ...):

wprowadź opis zdjęcia tutaj

Zdjęcie pochodzi z Wikipedii

Czy klient może delegować bezpośrednio do interfejsu strategii, czy też jest coś, czego mi brakowało, aby zrozumieć klasę kontekstu?

interface Reader {
    // read information from file and fill data list field of Client
    readFile();
}
class ExcelReader implements Reader{ /* */ }
class PdfReader implements Reader{ /* */}

class Client{
    // strategic choice
    Reader r;

    // data list field
    List<Data> data;

    // Client Constructor
    public Client(){
        if(<file ends in .xls>)
            r = new ExcelReader();
        else
            r = new PdfReader();
        r.readFile();
    }
}

Tak więc powyżej pokazano brak klasy kontekstu. Czy kod jest zgodny ze wzorem strategii?

rajstopy
źródło
1
Jako kolejną interesującą / ważną kwestię chciałbym zwrócić uwagę na to, że pojęcie klas typów w językach funkcjonalnych to „po prostu” wzorzec strategii z rodzajami en.wikipedia.org/wiki/Kind_(type_theory) ). Oba są tylko mechanizmem implementacji polimorfizmu ad hoc.
AndreasScheinert,
Czy jest to (daleko lub mniej) związane z Java 8 Project Lambda? Artykuł w Wikipedii jest zbyt gęsty, żebym od razu go zrozumiał, ale jeśli są one częścią teoretycznych podstaw efektywnego korzystania z nadchodzących funkcji Java (lub ogólnie programowania), chętnie zainwestuję w to więcej czasu.
panny
1
Bardzo daleko, ale twierdzę, że tak, klasy klas potrzebują. Język programowania obsługujący wyższe rodzaje. Tak byłoby w przypadku Scali i Haskella. Chodzi mi tutaj o to, że polimorfizm (ad hoc) jest wdrażany inaczej i jeśli się cofniesz, możesz nauczyć się kilku ogólnych spostrzeżeń na temat polimorfizmu.
AndreasScheinert

Odpowiedzi:

13

W twoim przykładzie wywołanie kodu readFilejest częścią konstruktora klienta. Ta metoda jest „kontekstem”, którego szukasz . Wzorzec strategii nie potrzebuje dosłownie „klasy kontekstu”, a w pierwszej wersji kodu obiekt strategii (w twoim przypadku „Reader”) może znajdować się tylko w zmiennej lokalnej. Zwłaszcza, gdy można wywołać tylko jedną „metodę strategiczną” („readFile”).

Jeśli jednak twoja baza kodu rośnie z jednej wersji do drugiej, nie jest prawdopodobne, aby wywoływano coraz więcej „strategicznych” metod, a decyzja, którą strategię zastosować i wykonanie „metod strategicznych” nastąpi w różnym czasie i w różnych miejscach w kodzie. Więc zaczynasz je refaktoryzować, aby zachować logikę w jednym miejscu. Doprowadzi to od razu do implementacji wyglądającej podobnie do diagramu w pytaniu.

Doktor Brown
źródło
5

Na pewno. Wzory są tylko wytycznymi. Nadal będziesz musiał je odpowiednio dostosować i zastosować do danego problemu. Osobiście rzadko pozwalam na ustawienie strategii w czasie wykonywania; częściej jest określany przy budowie lub rozwijany w fabryce.

Chociaż można również argumentować, że setStrategyjest prywatny, a mój zastrzyk po prostu używa wzoru, jak pokazano.

Telastyn
źródło
Czy to oznacza, że ​​przedstawioną klasę kontekstu można pominąć bez naruszenia wzoru? Innymi słowy, czy jest w porządku, gdy moja klasa klienta jest przedstawioną klasą kontekstu?
panny
6
@panny - waham się, czy odpowiedzieć na pytanie, ponieważ oznacza to, że nie trafiłeś w sedno odpowiedzi, a nawet wzorce. Wzorzec strategii pozwala zmieniać zachowanie poprzez dostarczanie różnych konkretnych implementacji za interfejsem. To jest koncepcja , a nie formuła .
Telastyn