Przejdź do zawartości

Wikipedysta:Jachuu007/Udaremnienie (wzorzec projektowy)

Z Wikipedii, wolnej encyklopedii

Wzorzec projektowy udaremniania albo rozgraniczania (balking) przewiduje możliwość wykonania określonej metody wyłącznie kiedy obiekt znajduje się w określonym stanie. Przykładowo, chodzi o sytuację gdy metoda danego obiektu jest w danym momencie wykonywana i nie jest bezpieczna wątkowo, równoległa próba wykonania tej metody w ramach innego wątku w tym samym czasie zostanie odrzucona. Odrzucenie wykonania może np. nastąpić poprzez zwrócenie odp. statusu z metody albo wyjątku (typowym wyjątkiem w Javie jest IllegalStateException), kiedy obiekt będzie przechowywał informację że jest w danym czasie zajęty.

Wzorzec ten jest również czasem uznawany za antywzorzec, ponieważ tak naprawdę nie rozwiązuje problemu synchronizacji i bezpiecznego wykonania metody w każdym przypadku. W niektórych przypadkach takie zabezpieczenie będzie wystarczające, np. gdy żądania wykonania metody generuje ten sam użytkownik, np. poprzez UI. Kolejne próby rozpoczęcia przetwarzania, uruchamiane kliknięciem przycisku na stronie WWW, będą się kończyć prezentacją błędu o tym że operacja już została zainicjowana i trwa albo będą one ignorowane. Inną sytuacją, kiedy zastosowanie tego wzorca w synchronizacji będzie wystarczające, jest kiedy metoda jest bezpieczna wątkowo tylko poza określonym zestawem parametrów, zwróci ona wyjątek jeśli zostanie podjęta próba równoległego wykonania dla określonego zestawu parametrów, czyli wyjątek będzie zabezpieczał przed niebezpiecznym wątkowo kontekstem zawołania (np. równoczesne uruchomienie funkcji operującej na tym samym obiekcie kontrahenta). Odpowiedzialność za bezbłędne użycie funkcji będzie spoczywała po stronie kodu używającego funkcji, jednak nigdy nie zdarzy się się sytuacja w której kod funkcji został wykonany nieprawidłowo przez dwa wątki na raz.

Implementacja

[edytuj | edytuj kod]

Poniżej przedstawiony został prosty przykład użycia wzorca udaremniania. Należy zwrócić uwagę na to że każde ustawianie statusu zajętości oraz sprawdzenie warunku musi być ujęte w sekcję krytyczną.

public class Example {
    private boolean jobInProgress = false;

    boolean void job() {
        synchronized(this) {
           if (jobInProgress) {
               return false;
           }
           jobInProgress = true;
        }
        // kod metody do wykonania
        // ...

        synchronized(this) {
            jobInProgress = false;
        }

        return true;
    }
}