![Pełnomocnik](/images/patterns/cards/proxy-mini.png?id=25890b11e7dc5af29625ccd0678b63a8)
Pełnomocnik w języku C#
Pełnomocnik to strukturalny wzorzec projektowy według którego obiekt-usługodawca używany przez klienta jest zastępowany przez obiekt zastępczy, zwany pełnomocnikiem. Pełnomocnik przechwytuje żądania od klienta, wykonuje jakąś pracę (kontrola dostępu, zarządzanie pamięcią podręczną, itp.) a następnie przekazuje żądanie usługodawcy.
Obiekt będący pełnomocnikiem ma ten sam interfejs co usługodawca, co czyni go wymienialnym z obiektem usługodawcy dotychczas przekazywanym klientowi.
Złożoność:
Popularność:
Przykłady użycia: Pełnomocnik nie jest częstym gościem w aplikacjach napisanych w C#, ale w niektórych wyjątkowych sytuacjach bardzo się przydaje. Jest niezastąpiony wszędzie tam, gdzie trzeba dodać jakąś funkcjonalność obiektowi istniejącej klasy bez zmiany kodu klienta.
Identyfikacja: Pełnomocnicy delegują całą faktyczną pracę innemu obiektowi. Każda metoda pełnomocnika powinna odnosić się do obiektu-usługodawcy, chyba, że pełnomocnik jest klasą pochodną usługi.
Przykład koncepcyjny
Poniższy przykład ilustruje strukturę wzorca Pełnomocnik ze szczególnym naciskiem na następujące kwestie:
- Z jakich składa się klas?
- Jakie role pełnią te klasy?
- W jaki sposób elementy wzorca są ze sobą powiązane?
Program.cs: Przykład koncepcyjny
using System;
namespace RefactoringGuru.DesignPatterns.Proxy.Conceptual
{
// The Subject interface declares common operations for both RealSubject and
// the Proxy. As long as the client works with RealSubject using this
// interface, you'll be able to pass it a proxy instead of a real subject.
public interface ISubject
{
void Request();
}
// The RealSubject contains some core business logic. Usually, RealSubjects
// are capable of doing some useful work which may also be very slow or
// sensitive - e.g. correcting input data. A Proxy can solve these issues
// without any changes to the RealSubject's code.
class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject: Handling Request.");
}
}
// The Proxy has an interface identical to the RealSubject.
class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy(RealSubject realSubject)
{
this._realSubject = realSubject;
}
// The most common applications of the Proxy pattern are lazy loading,
// caching, controlling the access, logging, etc. A Proxy can perform
// one of these things and then, depending on the result, pass the
// execution to the same method in a linked RealSubject object.
public void Request()
{
if (this.CheckAccess())
{
this._realSubject.Request();
this.LogAccess();
}
}
public bool CheckAccess()
{
// Some real checks should go here.
Console.WriteLine("Proxy: Checking access prior to firing a real request.");
return true;
}
public void LogAccess()
{
Console.WriteLine("Proxy: Logging the time of request.");
}
}
public class Client
{
// The client code is supposed to work with all objects (both subjects
// and proxies) via the Subject interface in order to support both real
// subjects and proxies. In real life, however, clients mostly work with
// their real subjects directly. In this case, to implement the pattern
// more easily, you can extend your proxy from the real subject's class.
public void ClientCode(ISubject subject)
{
// ...
subject.Request();
// ...
}
}
class Program
{
static void Main(string[] args)
{
Client client = new Client();
Console.WriteLine("Client: Executing the client code with a real subject:");
RealSubject realSubject = new RealSubject();
client.ClientCode(realSubject);
Console.WriteLine();
Console.WriteLine("Client: Executing the same client code with a proxy:");
Proxy proxy = new Proxy(realSubject);
client.ClientCode(proxy);
}
}
}
Output.txt: Wynik działania
Client: Executing the client code with a real subject:
RealSubject: Handling Request.
Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
RealSubject: Handling Request.
Proxy: Logging the time of request.