Drugi link od mike_mech powinien wszystko wyjaśnić.
Na wszelki wypadek ;)
Interfejsy pozwalają pisać lepiej zorganizowany, czytelniejszy kod oraz oddzielać implementację od właśnie interfejsu. Założenia programowania obiektowego mówią o tym, że powinno się pisać kod bardziej ukierunkowany na interfejs, niż samą implementację. Ułatwia to późniejsze ponowne wykorzystywanie kodu i współpracę między projektantami/programistami. Programowanie (w szczególności programowanie komponentowe
http://c2.com/cgi/wiki?ComponentOrientedProgramming) to nie tylko pisanie aplikacji dla końcowego użytkownika. Obecnie programiści piszą kod, który jest wykorzystywany/kupowany później przez innych programistów. Aby praca z obcymi komponentami czy bibliotekami była jak najłatwiejsza, czy też w ogóle możliwa, muszą one dostarczać czytelne API
http://en.wikipedia.org/wiki/API. Programistę wykorzystującego taki komponent nie interesuję implementacja (czyli w jaki sposób działają poszczególne zadania), a jedynie interfejs (czyli jakie zadania ma możliwość wykonać).
Mówiąc prościej… interfejs w odniesieniu do obiektu to po prostu lista metod jakie obiekt posiada wraz z typami niezbędnych parametrów i informacją o zwracanej wartości. php umożliwia wymuszanie jedynie typów obiektowych jako parametrów funkcji. Gorzej jest z wartościami zwracanymi, ale ma się to zmienić
http://www.php.net/~derick/meeting-notes.h...d-return-values. Póki co jedyny sposób to dobra dokumentacja kodu
http://phpdoc.org/.
W taki sposób znając interfejs obiektu wiemy jak go używać. Bo zgodnie z ideą interfejsu wszystkie jego metody muszą być publiczne.
Jak sprawa ma się w praktyce?
Załóżmy, że mamy napisaną aplikację opartą o Front Controller
http://www.phppatterns.com/docs/design/the...troller_and_php, który stanowi punkt wejścia do naszej aplikacji. Możemy w nim rejestrować filtry
http://java.sun.com/blueprints/corej2eepat...tingFilter.html, które będą wykonywały jakieś operacje na danych wejściowych i wyjściowych. Idea polega na tym, że wykorzystując nasz kontroler w różnych przypadkach, możemy dowolnie komponować zestawy filtrów, lub też tworzyć nowe w miarę potrzeb. W tym celu tworzymy interfejs filtru, z którym będzie współpracował obiekt kontrolera.
<?php
interface IInterceptingFilter
{
/**
* Operacje wykonywane przed wywołaniem kontrolera
*
* @param Request Obiekt żądania
* @return Request
* @access public
**/
public function preProcess( Request $oRequest );
/**
* Operacje wykonywane po obsłudze żądania
*
* @param Response Obiekt odpowiedzi
* @return Response
* @access public
**/
public function postProcess( Response $oResponse );
}
?>
Stwórzmy teraz przykładowy filtr:
<?php
class TimeExecutionFilter implements InterceptingFilter
{
/**#@+
* @var string
* @access private
*/
/**
* Data rozpoczęcia skryptu (format microtime)
*/
private $_sStart;
/**
* Data zakończenia wykonywania skryptu (format microtime)
*/
private $_sEnd;
/**#@-*/
public function preProcess( Request $oRequest )
{
return $oRequest;
}
public function postProcess( Response $oResponse )
{
return $oResponse->set( 'time', $this->_calculateTime( $this->_sStart, $this->_sEnd ) );
}
/**
* Przeliczenie czasu wykonania strony
*
* @param string Czas rozpoczęcia (format microtime)
* @param string Czas zakończenia (format microtime)
* @return double Czas wykonania w sekundach
* @access private
**/
private function _calculateTime( $sStart, $sEnd )
{
$dEnd = (float) $aEnd[1] + (float) $aEnd[0];
$dStart = (float) $aStart[1] + (float) $aStart[0];
}
}
?>
Z czasem rozwoju aplikacji może się okazać, że przydałby nam się jeszcze inne filtry. Nie ma problemu wystarczy, że zaimplementujemy na nowo nasz interfejs lub zlecimy to komuś innemu. Tak długo jak będziemy trzymać się interfejsu kontroler będzie potrafił sobie z nim poradzić, a my będzimy mogli go spokojnie używać. Chociażby w taki sposób:
<?php
$oController = new FrontController();
$oController->addFilter( new AuthenticationFilter( 'login.php' ) );
$oController->addFilter( new OutputBufferFilter() );
$oController->addFilter( new TimeExecutionFilter() );
$oController->run();
?>