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ésA 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ésA 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ésA 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ésclass 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ésJegyzetek
szerkesztésTová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ésEz 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.