Helyettes programtervezési minta
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]- Helyettes minta UML-ben és LePUS3-ban (egy formális modellező nyelv)
- Take control with the Proxy design pattern by David Geary, JavaWorld.com
- PerfectJPattern Open Source Project, Provides componentized implementation of the Proxy Pattern in Java
- Adapter vs. Proxy vs. Facade minta összehasonlítása
- Helyettes tervezési minta
- Proxy pattern description from the Portland Pattern Repository
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.