MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Interfețele în mecanismul de callback

Unul dintre modurile comune de utilizare a interfețelor în Java este crearea unui mecanism de callback. Esența unui callback constă în faptul că creăm acțiuni care sunt declanșate de alte acțiuni. Cu alte cuvinte, unele acțiuni sunt inițiate de altele. Un exemplu standard este apăsarea unui buton.

Când apăsăm pe un buton, executăm o acțiune, dar, ca răspuns la această apăsare, sunt declanșate alte acțiuni. De exemplu, apăsarea pictogramei de imprimantă declanșează imprimarea unui document pe imprimantă și așa mai departe.

Să analizăm următorul exemplu:

public class EventsApp {
   public static void main(String[] args) {
       Button button = new Button(new ButtonClickHandler());
       button.click();
       button.click();
       button.click();
   }
}

class ButtonClickHandler implements EventHandler {
   public void execute() {
       System.out.println("Butonul a fost apăsat!");
   }
}

interface EventHandler {
   void execute();
}

class Button {
   EventHandler handler;
   Button(EventHandler action) {
       this.handler = action;
   }
   public void click() {
       handler.execute();
   }
}

Aici avem definită clasa Button, care, în constructor, primește un obiect al interfeței EventHandler și în metoda click (simulând apăsarea) apelează metoda execute a acelui obiect.

Apoi se definește implementarea interfeței EventHandler sub forma clasei ButtonClickHandler. În programul principal, un obiect al acestei clase este transmis constructorului clasei Button. Astfel, prin constructor, stabilim un handler pentru apăsarea butonului. La fiecare apel al metodei button.click(), acest handler va fi executat.

Rezultatul afișat în consolă va fi următorul:

Butonul a fost apăsat!
Butonul a fost apăsat!
Butonul a fost apăsat!

S-ar putea să ne întrebăm de ce mutăm toate acțiunile în interfață și le implementăm, în loc să scriem direct în clasa Button, ca în exemplul următor:

class Button {
   public void click() {
       System.out.println("Butonul a fost apăsat!");
   }
}

Motivul este că, în momentul definirii clasei, nu știm întotdeauna exact ce acțiuni trebuie să se execute. Acest lucru este valabil mai ales dacă clasa Button și clasa principală se află în pachete sau biblioteci diferite și sunt proiectate de dezvoltatori diferiți. De asemenea, pot exista mai multe butoane - obiecte ale clasei Button, și pentru fiecare obiect trebuie să definim o acțiune specifică. De exemplu, să modificăm clasa principală a programului:

public class EventsApp {
   public static void main(String[] args) {
       Button tvButton = new Button(new EventHandler() {
           private boolean on = false;
           public void execute() {
               if(on) {
                   System.out.println("Televizorul este oprit.");
                   on = false;
               } else {
                   System.out.println("Televizorul este pornit!");
                   on = true;
               }
           }
       });
       
       Button printButton = new Button(new EventHandler() {
           public void execute() {
               System.out.println("Imprimarea a început...");
           }
       });
       
       tvButton.click();
       printButton.click();
       tvButton.click();
   }
}

Aici avem două butoane - unul pentru pornirea/oprirerea televizorului și altul pentru imprimarea la imprimantă. În loc să creăm clase separate care să implementeze interfața EventHandler, handler-ele sunt definite sub formă de obiecte anonime care implementează interfața EventHandler.

În plus, handler-ul butonului pentru televizor stochează o stare suplimentară sub forma unei variabile booleene on.

Rezultatul afișat în consolă va fi:

Televizorul este pornit!
Imprimarea a început...
Televizorul este oprit.

În concluzie, trebuie menționat că interfețele sunt utilizate pe scară largă în diferite API-uri grafice - AWT, Swing, JavaFX, unde gestionarea evenimentelor pentru elementele interfeței grafice este deosebit de relevantă.

← Lecția anterioară Lecția următoare →