Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

Klasy abstrakcyjne w PHP 4

Przykład: Interfejsy

W tym przykladzie przedstawię zastosowanie klas abstrakcyjnych jako interfejsów. Na początek stworzymy kilka obiektów, które będą elementami naszej fikcyjnej aplikacji webowej służącej do sterowania różnymi urządzeniami w naszym domu przyszłości(jest to jedno z moich hobby). Chcemy zbudować interfejs webowy, który umożliwi Nam sterowanie różnymi urządzeniami w domu. Niestety nie wszystkie urządzenia komunikają się w tym samym języku oraz nie korzystają z tych samych protokołów. Najczęściej spotykanym protokołem jest X-10, jednakże na rynku można znaleść kilka innych. Cztery najbardziej znane protokoły to

  • X-10
  • LONworks
  • CEBus(EIA IS-60)
  • Smart House

Implementacje wszytkich tych protokołów znacząco się różnią, jednakże każdy z nich zawiera conajmniej trzy metody("funkcjonalności"):

  1. Włączanie urządzenia
  2. Wyłączanie urządzenia
  3. Pobieranie statusu urządzenia

Nasz zaimplementowany w PHP interfejs będzie szablonem dla każdej z klas zapewniając jej podstawową funkcjonalność opisaną powyżej. Nasz interfejs nazwieny Kontrolką("Control"). Jak widać poniżej żadna z metod nie zawiera jakiegokolwiek kodu.

<?php
class Control
{
	function on();
	function off();
	function getStatus();
}
?>

Jak wcześniej napomknąłem nasz kod musi być dobrze skometowany. To pomaga osobie implementującej nasz interfejs zrozumieć jakie zachowanie jest oczekiwane. Tak dopiszmy kilka komentarzy do naszego interfejsu.

<?php
/*
* Klasa: Control
* Typ: Interfejs
*
* Przeznaczenie - zapewnienie podstawowej funkcjonaliści kontrolkom służącym sterowaniu domu przyszłości
* Metody:
* on()
* off()
* getStatus()
*
* Kody błędów
* ---------------------
* 0 - Brak błędów podczas transmisji
* 1 - Wysiąpil błąd podczas transmisji
*
*
* Notka dla implementujących kontrolki w oparciu o ten interfejs
* ----------------------------------------------------------------
* Każda z metod musi posiadać implementację
* Protokoły są dynamicznie inicjalizowane przez aplikację
* Aplikacja oczekuje funkcjnalności pokazanej w interfejsie
*/

class Control
{
	function Control()
	{
		/*
		*Nie pozwalamy na stworzenie instancji klasy Control
		*Nie pozwalamy na wywołanie kontruktora przez podklasę
		*/
		if(!is_subclass_if($this,"Control"))
		{
			trigger_error("Instancja klasy Control jest zabroniona.",E_USER_ERROR);
			return NULL;
		}
	}

	function on(); // włącza urządzenie
	function off(); // wyłącza urządzenie
	function getStatus(); //Pobiera status urządzenia
}
?>

OK, teraz mając zdefiniowany interfejs może spróbować zaimplementować jeden z protokołów. Jakoże X-10 jest najpopularniejszym protokołem tak więc zaczniemy od niego. Oczywiście wykorzystamy wcześniej stworzoną Kontrolkę której zaimplementujemy w odpowiedni sposób wymagane metody.

<?php
class X10_Control extends Control
{
	function off()
	{
		//implementacja metody
	}

	function on()
	{
		//implementacja metody
	}

	function getStatus()
	{
		//implementacja metody
	}

	function dim()
	{
		//implementacja metody
	}

	function bright()
	{
		//implementacja metody
	}
}
?>

Nietrudno zauważyc dodatek w postaci dwóch nowych metod - dim() oraz bright(). Ta funkcjonaność jest dostępna w protokole X-10, ale może nie być dostępna w innych. Tak więc jest to luksusowy dodatek ;). Nasza klasa do obsługi protokołu X-10 jest kompletna tak więc teraz pokusimy się o jej wykorzystanie przy sterowaniu urządzeń w naszym domu. Tak więc na początek stwórzmy sobię klasę urządzenia podobną do tej przedstawionej poniżej. Spójrzmy

<?php
class Device
{
	//zmienne klasy
	var $_type;
	var $_protocol;
	
	function Device($deviceID)
	{
		//Pobieramy ustawienia urządzenia z konfiguracji
		$deviceRS = DataProvider::getDevice($deviceID);
		
		//przypisujemy pobrane dane do zmiennych klasy
		$this->_type=$deviceRS->type; //lodówka, radio
		$this->_protocol=$deviceRS->protocol; // X10

		//przypisujemy protokół urządzeniu
		aggregate($this,$this->_protocol."_Control");
	}

	function setProtocol($protocol)
	{
		//usuwamy poprzednie przypisania
		deaggregate($this,$this->_protocol."_Control");
		
		//nadpisujemy protokół
		$this->_protocol=$protocol;

		//przypisujemy nowy protokół urządzeniu
		aggregate($this,$this->_protocol."_Control");
	}
}
?>

Zadeklarowaliśmy dwie zmienne wewnątrz klasy - jedną, aby mieć informację jaki typ urządzenia obsługujemy oraz drugą, aby mieć informację z jakiego protokołu korzystamy. W konstruktorze pobieramy konfigurację urządzenia, przypisujey jej ustawienia do instancji naszej klasy, potem uruchamiamy odpowiedni protokół sterujący bazując na pobranej konfiguracji. Na boku można wspomnieć, iż PHP obsługuje dwie metody przypisania: agregację oraz asocjację. Protokół jest przypisywany przez agregację. My dzieki stworzonej klasie możemy zmieniać w dowolny sposób protokół, który wykorzystuje urządzenie; nawet podczas działania aplikacji. Dziś nasz garaż jest kompatibilny z protokołoem X-10, jutro z protokołem Smart House. Zakończmy nasze rozważania dot. interfejsów przedstawiając przykład jak możemy zamknąć to wszystko w jedno i zastosować w naszej aplikacji. Wyobraźmy sobie w naszej głowie listę zautomatyzowanych urządzeń, które znajdują się w naszym domu. Koło każdego z urządzeń na naszej liście znajduje się pole do odznaczenia, służace do wyboru urządzenia, którym chcemy sterować. Po wybraniu urządzenia użytkownik ma możliwość wyboru jednej z trzech komend: włącz("ON"), wyłącz("OFF"), stan urządzenia("STATUS").W skrypcie obsługującym dana komenda jest wysyłana do każdego urządzenia, które zostało zaznaczone na liście. Skrypt obsługujący nie wie jaki protokół jest zaimplementowany w danym urządzeniu. Wie natomiast,że każde z urządzeń posiada implementację interfejsu Kontrolki("Control"), tak więc wynika z tego, iż posiada metody służace do włączania, wyłączania oraz pobierania statusu urządzenia. Kod przedstawiony poniżej pokazuje Nam w praniu to co żeśmy napisali w kilku poprzednich zdaniach.

<?php
//Pętla, wysyłająca wybraną przez użytkownika komendę do wszystkich zaznaczonych urządzeń
foreach($_POST['devices'] as $deviceID => $selected)
{
	$device=Device::getDevice($deviceID);
	
	switch($_POST['command'])
	{
		case 'on': $device->on(); break;

		case 'off': $device->off(); break;

		case 'getStatus': $device->getStatus(); break;
	}
}
?>
Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (4)
Literówka c.d.
Środa 21 Marzec 2007 3:24:56 pm - skyfly <przemekkus_at_interia.pl>

listingach :)

Literówka
Środa 21 Marzec 2007 3:23:49 pm - skyfly <przemekkus_at_interia.pl>

We wszystkich listningach zamiast "is_subclass_if" ma być oczywiście "is_subclass_of".

abstrakcja
Sobota 28 Styczeń 2006 6:18:42 pm - emp

Abstrakcja jest ale nie ma dziedziczenia wielorakiego.. tylko interfejsy a to jest kapa w prownaniu z mozliwosciami jakie daje welorakie dziedziczenie... jak mozna usuwac jakies udogodnienia tylko dlatego ba sa programisci ktorzy nie umieja z nich skorzystac... przyklad javy rezygnacia z wiekszosci udogodnien jest spowodowana tym by programisci popelniali mniej bledow .. chory pomysl tak offtopik ;)

Brak danych
Piątek 13 Styczeń 2006 10:45:21 pm - ..:: pingu ::.. <pingu_at_interia.pl>

literowka w podstronie:
Implementacja klas abstrakcyjnych w PHP 4.
na samym koncu (tzn koncowy akapit)
W PHP 4 nie ma różnicuy pomiędzy metodą abstrakcyjną oraz nieabstrakcyjną

Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2022 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System