Helyettes programtervezési minta

Helyettes UML-ben
Helyettes LePUS3-ban (legend)

A számítástudományban a helyettes minta vagy helyettesítő minta egy programtervezési minta.

Egy helyettes a legáltalánosabb formájában egy olyan osztály funkcionalitása, amely egy interfész valami máshoz. A helyettes interfészként tud viselkedni valamihez: egy hálózati kapcsolathoz, egy nagy objektumhoz a memóriában, egy fájlhoz vagy számos más erőforráshoz, amely költséges vagy lehetetlen duplikálni.

A helyettes programtervezési mintára egy jól ismert példa egy referencia számláló mutató objektum.

Olyan esetekben, ahol egy összetett objektum több példányának kell léteznie, a helyettesítő minta adaptálható a pehelysúlyú mintára, azért hogy csökkentse az alkalmazás memóriában elfoglalt méretét. Tipikus módon az összetett objektumból 1 példány és sok helyettes objektum készül, melyek tartalmaznak az egy darab eredeti összetett objektumra mutató referenciát. Bármilyen művelet végrehajtása a helyettesítőkön az eredeti objektumnak való továbbítást jelent. Amint az összes helyettes példány érvényessége megszűnik, az összetett objektum tárhelye felszabadíthatóvá válik.

Használata[szerkesztés]

A helyettes megvalósítja az eredeti objektum interfészét. Információkat rejthet el, kérésre végezhet optimalizációt vagy betöltést. Elláthat további feladatokat is, mint auditálás vagy naplózás.

A védelmi helyettes ellenőrzi a hozzáférést, és csak megfelelő jogosultság esetén engedélyezi.

A virtuális helyettes egy erőforrás-igényes objektumot helyettesít, és csak akkor tölti be, ha tényleg szükség van az eredeti objektumra.

A távoli helyettes egy távoli objektumot reprezentál helyben, és ha metódushívás történik, akkor továbbítja a távoli objektumnak. Például az ATM automaták így állnak kapcsolatban a bankkal.

A helyettes tesztelési célra is használható, ekkor fake, stub vagy mock objektum a neve.

Példák[szerkesztés]

A következő Java példa a "virtuális helyettes" mintát szemlélteti. A ProxyImage osztály használható egy távoli metódus eléréséhez.

A példa először létrehoz egy interfészt, amihez a minta szerint létrehozzuk a megvalósító osztályokat. Ez az interfész csak egy metódust tartalmaz, amely megjeleníti a képet (displayImage()), és ezt kell lekódolni az összes osztálynak, amely azt megvalósítja.

A helyettes osztály a ProxyImage egy másik rendszerben fut, mint a valódi kép osztály maga és reprezentálja a valódi osztályt RealImage a felett. A kép információk elérhetők a lemezről. A helyettes minta használatával a ProxyImage kódja elkerüli a kép többszöri betöltését, elérhetővé téve azt egy másik rendszerből memóriatakarékos módon.

interface Image {     public void displayImage(); }  //on System A  class RealImage implements Image {      private String filename = null;     /**      * Constructor      * @param FILENAME      */     public RealImage(final String FILENAME) {          filename = FILENAME;         loadImageFromDisk();     }      /**      * Loads the image from the disk      */     private void loadImageFromDisk() {         System.out.println("Loading   " + filename);     }      /**      * Displays the image      */     public void displayImage() {          System.out.println("Displaying " + filename);      }  }  //on System B  class ProxyImage implements Image {      private RealImage image = null;     private String filename = null;     /**      * Constructor      * @param FILENAME      */     public ProxyImage(final String FILENAME) {          filename = FILENAME;      }      /**      * Displays the image      */     public void displayImage() {         if (image == null) {            image = new RealImage(filename);         }          image.displayImage();     }  }   class ProxyExample {     /**     * Test method     */    public static void main(String[] args) {         final Image IMAGE1 = new ProxyImage("HiRes_10MB_Photo1");         final Image IMAGE2 = new ProxyImage("HiRes_10MB_Photo2");                  IMAGE1.displayImage(); // loading necessary         IMAGE1.displayImage(); // loading unnecessary         IMAGE2.displayImage(); // loading necessary         IMAGE2.displayImage(); // loading unnecessary         IMAGE1.displayImage(); // loading unnecessary     }  } 

A program kimenete:

Loading   HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading   HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1 

C#[szerkesztés]

A következő C# és C++ példa a védelmi helyettest szimulálja.

interface ICar {     void DriveCar(); }  // Real Object public class Car : ICar {     public void DriveCar()     {         Console.WriteLine("Car has been driven!");     } }  //Proxy Object public class ProxyCar : ICar {     private Driver driver;     private ICar realCar;      public ProxyCar(Driver driver)     {         this.driver = driver;         this.realCar = new Car();     }      public void DriveCar()     {         if (driver.Age <= 16)             Console.WriteLine("Sorry, the driver is too young to drive.");         else             this.realCar.DriveCar();      } }  public class Driver {     private int Age { get; set; }      public Driver(int age)     {         this.Age = age;     } }  // How to use above Proxy class? private void btnProxy_Click(object sender, EventArgs e) {     ICar car = new ProxyCar(new Driver(16));     car.DriveCar();      car = new ProxyCar(new Driver(25));     car.DriveCar(); } 

Kimenet:

Sorry, the driver is too young to drive. Car has been driven! 

C++[szerkesztés]

class ICar { public:   virtual void DriveCar() = 0; };  class Car : public ICar {   void DriveCar() override {     std::cout << "Car has been driven!" << std::endl;   } };  class ProxyCar : public ICar { private:   ICar* realCar = new Car();   int _driver_age;  public:   ProxyCar (const int driver_age) : _driver_age(driver_age) {}    void DriveCar() {     if (_driver_age > 16)       realCar->DriveCar();     else       std::cout << "Sorry, the driver is too young to drive." << std::endl;   } };  // How to use above Proxy class? void main() {     ICar* car = new ProxyCar(16);     car->DriveCar();     delete car;      car = new ProxyCar(25);     car->DriveCar();     delete car; } 

Kapcsolódó szócikkek[szerkesztés]

Jegyzetek[szerkesztés]

További információk[szerkesztés]

Az angol Wikikönyvekben
további információk találhatók

Fordítás[szerkesztés]

Ez a szócikk részben vagy egészben a Proxy pattern című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.