Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Klasa odwołująca się do sterownika
Forum PHP.pl > Forum > PHP > Object-oriented programming
mstraczkowski
Witam was,

Mam drobne pytanie, bo albo już jestem przemęczony, albo nie wiem.

Co chcę osiągnąć:

Chcę utworzyć obiekt klasy, do której będę się odwoływać, natomiast nie będę odwoływał się tak naprawdę bezpośrednio do niej, tylko do jej adaptera, który jest ustalany na podstawie konfiguracji.

Przykładowo klasa Cache, posiada możliwe 3 adaptery: file, apc lub memcached, wybrany w konfiguracji jest apc, chciałbym teraz móc zrobić tak:

Cytat
Uwaga: Nie chcę robić przykładowo Cache::getInstance(), aby otrzymać obiekt adaptera, chcę działać na obiekcie klasy Cache.


  1. <?php
  2. // Wybrany w konfiguracji apc
  3. $cache = new Cache();
  4. $cache->store(); // Skutkuje wywołaniem metody store w adapterze APC
  5.  
  6. // Zmieniam sobie konfigurację na file
  7. $cache = new Cache();
  8. $cache->store(); // Skutkuje wywołaniem metody store w adapterze File

Każda klasa adaptera rzecz jasna implementuje interfejs, więc zbiór ich metod jest taki sam

Moje rozwiązanie:

Rozwiązałem to zagadnienie używając metody magicznej __call, która uruchomi się wtedy gdy danej metody nie ma w klasie Cache, wtedy ta metoda jest wykonywana z wybranego adaptera.

Moje pytanie

Czy jest jakiś lepszy sposób na osiągnięcie opisanego przeze mnie efektu ?

Pozdrawiam i dzięki za sugestie.
nospor
Raczej nie ma innej metody.
Od biedy możesz w klasie Cache stworzyć metode store() a tej metodzie odpalać metodę store() aktualnego adaptera. No ale to wcale nie jest lepsze rozwiązanie smile.gif
mstraczkowski
@up Tak, też to brałem to pod uwagę i też uważam, że to nie jest lepsze rozwiązanie - zbędne pisanie kodu moim zdaniem.
melkorm
No na pewno będzie to czytelniejsze rozwiązanie niż __call moim zdaniem.
nospor
Cytat
No na pewno będzie to czytelniejsze rozwiązanie niż __call moim zdaniem.
ALe upierdliwe.... bedziesz miał 10 metod do wykonania to będziesz musial pisać 10 metod w cache. A tak jeden call i już

Można zrobić tablicę z nazwami metod, które można wywoływać w adapter i w ten sposób przez call wywoływać tylko te, które są w tablicy
melkorm
Hum, jednorazowe napisanie metod, a wygoda czyli podpowiedzi IDE itp, cóż moim zdaniem kwestia podejścia smile.gif
nospor
Cytat
cóż moim zdaniem kwestia podejścia
Racja smile.gif

mstraczkowski
Tzn wiesz, podczas rozwijania kodu doszła by nowa metoda, wtedy musimy dodać ją do każdego sterownika + interfejs + klasa główna.
m.in dlatego zadałem to pytanie bo IDE mało podpowiada przy takim zastosowaniu, ale tak jak mówisz to już kwestia podejścia.
melkorm
Cytat
Tzn wiesz, podczas rozwijania kodu doszła by nowa metoda, wtedy musimy dodać ją do każdego sterownika + interfejs + klasa główna.


Załóżmy że masz 3 sterowniki i interejs to musisz dodać metodę w 4 miejscach mając __call, mając proxy metody w Cache musiałbyś dodać o jedną metodę więcej niż w przypadku __call, dla mnie nigdy nie stwarzało to problemu, chwila roboty za czytelność - ale jak już mówiłem kwestia podejścia.
CuteOne
Cytat
Chcę utworzyć obiekt klasy, do której będę się odwoływać, natomiast nie będę odwoływał się tak naprawdę bezpośrednio do niej, tylko do jej adaptera

http://www.oodesign.com/factory-pattern.html
Crozin
1. Skoro wszystkie sterowniki (powiedzmy: APCCache, FileCache i ArrayCache) implementują wspólny interfejs i tylko on Cie obchodzi to nic nie stoi na przeszkodzie by rozwiązać to tak:
  1. /** @var $cache My\CacheInterface */
  2. $cache = new APCCache();
2. Jednak domyślam się, że w Twoim przypadku APC, File czy Array to jedynie miejsce składowania danych, a obiekty te zapewne mają jedynie metody get(), set(), has(). Zaś sama klasa Cache może mieć już jakieś bardziej złożone metody, które jedynie korzystają ze "składowiska" cache'u. Dlatego też najprawdopodobniej powinieneś to rozwiązać w ten sposób:
  1. $cache = new Cache(new APCStorage()); // albo: new Cache(new FileStorage('/path/to/dir'));
3. Jeżeli część/wszystkie metody z obiektu APCStorage miałby być również dostępne bezpośrednio przez obiekt Cache powinieneś dla każdej metody utworzyć metodę proxy, a nie stosować żadnego porąbanego __call(). Dlaczego __call() jest porąbane?
3.1. Zamiast n metod proxy masz jedną, w której masz n skomplikowanych IF-ów sprawdzających czy nazwa metody jest w ogóle w porządku oraz czy jej argumenty są poprawne (ilość, typ).
3.2. Tracisz wsparcie ze strony IDE, narzędzi dokumentujących czy ogólnie analizujących kod.
3.3. Kilka rodzajów błędów, które normalnie można wykryć na etapie "kompilacji" (w przypadku PHP trzeba tutaj ująć to w spory cudzysłów) staje się błędami czasu wykonywania - czyli stają się gorszymi błędami.
3.4. PHP nie ma co prawda jakiś specjalnych optymalizatorów o JIT-cie nie wspominając, ale może niedługo coś się z tym tematem ruszy - Twój kod nie skorzysta na tym. Google: PHP HipHop

@CuteOne: Fabryka? Jakie niby miałaby mieć tutaj zastosowanie?
mstraczkowski
Dzięki wielkie za sugestię, zastosuję metody proxy, wsparcie IDE jest dla mnie dosyć ważną rzeczą.
viking
Ja po przeczytaniu też zrozumiałem że chodzi o fabrykę. Czyli wywoływanie
  1. $cache = Cache::factory('Apc', $options);

gdzie te obiekty implementują jakąś abstrakcję albo interface'y stąd późniejsze
  1. $cache->store()

niezależne od adaptera cache.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.