Heim > Artikel > Backend-Entwicklung > Verstehen Sie das Proxy-Muster von PHP-Entwurfsmustern in einem Artikel
Das Proxy-Muster ist ein strukturelles Entwurfsmuster, das auf die klassische Struktur abzielt, in der Klassen und Objekte kombiniert werden. Das Proxy-Muster ist ebenfalls ein häufig verwendetes Entwurfsmuster, auf das wir uns konzentrieren müssen. Es kann einige zusätzliche Funktionen hinzufügen, ohne das Zielobjekt zu ändern.
Definition
Proxy-Muster (Proxy) stellt einen Proxy für andere Objekte bereit, um den Zugriff auf dieses Objekt zu steuern. Verwenden Sie das Proxy-Muster, um ein Proxy-Objekt zu erstellen. Lassen Sie das Proxy-Objekt den Zugriff auf das Zielobjekt steuern (das Zielobjekt kann ein Remote-Objekt, ein Objekt sein, dessen Erstellung teuer ist, oder ein Objekt, das eine Sicherheitskontrolle erfordert). Fügen Sie einige Extras hinzu, ohne die Zielfunktion zu ändern.
Frage
Derzeit verfügt das System über eine Login-Klasse für Benutzeranmeldungs- und Registrierungsgeschäfte. Der Pseudocode lautet wie folgt:
class UserLogin { // …… 省略属性和部分方法 public function login ($name, $pass) { // 登录业务 } public function reg ($name, $pass) { // 注册业务 } }
Jetzt möchten wir dem Benutzeranmelde- und Registrierungsgeschäft eine Funktion hinzufügen – Strombegrenzung, die die Häufigkeit, mit der der Client diese Methode aufruft, auf maximal 5 Mal pro Sekunde begrenzt . Nun implementieren wir diese Funktion wie folgt:
class UserLogin { // …… 省略属性和部分方法 public function login ($name, $pass) { // 限流 $limit = new Limit(); if ($limit->restrict()) { // …… } // 登录业务 } public function reg ($name, $pass) { // 限流 $limit = new Limit(); if ($limit->restrict()) { // …… } // 注册业务 } }
Schauen Sie sich den obigen Code an. Erstens dringt der aktuelle Begrenzungscode in den Geschäftscode ein Geschäftscode. Zweitens hat die Strombegrenzung nichts mit dem Geschäftskodex zu tun und verstößt gegen das Prinzip der Einzelverantwortung.
Implementierung
Als nächstes schreiben wir den obigen Code im Proxy-Modus neu. Der neu geschriebene Code sieht so aus:
interface IUserLogin { function login (); function register (); } class UserLogin implements IUserLogin { // …… 省略属性和部分方法 public function reg ($uname, $pass) { // 注册业务 } public function login ($uname, $pass) { // 登录业务 } } class UserLoginProxy implements IUserLogin { private $limit = null; private $login = null; public function __construct(Limit $limit, Login $login) { $this->limit = $limit; $this->login = $login; } public function login($uname, $pass) { if ($this->limit->restrict()) { // ... } return $this->login->login($uname, $pass); } public function register($uname, $pass) { if ($this->limit->restrict()) { // ... } return $this->login->register($uname, $pass); } }
Die obige Methode basiert auf der Designidee der Schnittstelle und nicht auf der Implementierungsprogrammierung. Wenn die ursprüngliche Klasse jedoch keine Schnittstelle definiert oder diese Klasse nicht von uns entwickelt und verwaltet wird, wie implementiert man dann den Proxy-Modus?
Für die Erweiterung dieser externen Klasse verwenden wir im Allgemeinen die Vererbung.
class UserLogin { public function reg ($uname, $pass) { // 注册业务 } public function login ($uname, $pass) { // 登录业务 } } class UserLoginProxy extends Login { private $limit = null; public function __construct(Limit $limit, Login $login) { $this->limit = $limit; $this->login = $login; } public function login($uname, $pass) { if ($this->limit->restrict()) { // ... } return parent::login($uname, $pass); } public function reg($uname, $pass) { if ($this->limit->restrict()) { // ... } return parent::register($uname, $pass); } }
Sehen Sie sich den obigen Code an. Sie werden feststellen, dass der ähnliche Code
if ($this->limit->restrict()) { // ... }
zweimal vorkommt. Jetzt fügen wir einfach die aktuelle Begrenzungsfunktion zu zwei Methoden hinzu. Wenn die UserLogin-Klasse 10 Methoden hat und wir die aktuelle Begrenzungsfunktion zu jeder Methode hinzufügen möchten, müssen wir diesen Code zehnmal kopieren. Wenn wir allen Methoden in 10 Klassen eine Strombegrenzungsfunktion hinzufügen möchten und jede Klasse über 10 Methoden verfügt, wird der obige Strombegrenzungscode 100 Mal wiederholt.
Natürlich werden Sie sagen, dass ich den aktuellen Begrenzungscode in eine Funktion kapseln kann, um das obige Problem zu lösen? Es gibt jedoch immer noch ein Problem, das nicht gelöst werden kann. Jede Methode in der ursprünglichen Klasse muss in der Proxy-Klasse erneut implementiert werden. So wie es in der oben genannten Originalklasse reg- und login-Methoden gibt, gibt es auch in der Proxy-Klasse reg- und login-Methoden.
Dynamischer Proxy
Um die oben genannten Probleme zu lösen, können wir einen dynamischen Proxy verwenden, um es zu lösen. Wenn Sie einen dynamischen Proxy verwenden möchten, müssen Sie den Reflexionsmechanismus in PHP verstehen und verwenden.
php verfügt über eine vollständige Reflexions-API, die die Möglichkeit bietet, Klassen, Schnittstellen, Funktionen, Methoden und Erweiterungen zurückzuentwickeln. Darüber hinaus stellt die Reflection-API Methoden zum Extrahieren von Dokumentationskommentaren aus Funktionen, Klassen und Methoden bereit. Auf die Kenntnisse im Zusammenhang mit der PHP-Reflexion werde ich hier nicht näher eingehen. Sie können die relevanten Informationen selbst überprüfen.
Beachten Sie, dass die Verwendung von Reflektion viel Leistung verbraucht. Verwenden Sie sie daher bitte nicht unter normalen Umständen.
Lassen Sie uns zeigen, wie Sie mithilfe von Reflection einen dynamischen Proxy implementieren. Der Pseudocode lautet wie folgt:
class UserLogin { public function reg ($uname, $pass) { // 注册业务 echo '注册业务' . PHP_EOL; } public function login ($uname, $pass) { // 登录业务 echo '登录业务' . PHP_EOL; } } class LimitProxy { // 用来保存多个实例对象 private $target = []; public function __construct(Object $obj) { $this->target[] = $obj; } public function __call($name, $arguments) { foreach ($this->target as $obj) { $ref = new \ReflectionClass($obj); if ($method = $ref->getMethod($name)) { if ($method->isPublic() && !$method->isAbstract()) { // 限流 echo "这里是限流业务处理" . PHP_EOL; $result = $method->isStatic() ? $method->invoke(null, $obj, ...$arguments) : $method->invoke($obj, ...$arguments); return $result; } } } } }
Der Testcode lautet wie folgt:
$login = new Login(); $loginProxy = new LimitProxy($login); $loginProxy->reg('gwx', '111111'); $loginProxy->login('james', '111111111');
Anwendungsszenario
Zugangskontrolle (Schutzmittel). Das System verfügt beispielsweise über ein Bestellmodul. Ursprünglich verfügte dieses Modul auch über eine Berechtigungskontrolle, aber jetzt möchten wir, dass es nur für Clients mit bestimmten IP-Adressen zugänglich ist. Dann können wir den Proxy-Modus verwenden.
Die lokale Ausführung von Remote-Diensten (Remote-Proxy) eignet sich für Situationen, in denen sich das Dienstobjekt auf einem Remote-Server befindet.
Entwickeln Sie einige nicht funktionale Anforderungen im Geschäftscode, z. B.: Strombegrenzung, Statistiken, Protokollierung
Caching-Anwendungen, zum Beispiel hinzufügen ein Cache-Proxy, wenn der Cache vorhanden ist, wird der Cache-Proxy aufgerufen, um die zwischengespeicherten Daten abzurufen. Wenn der Cache nicht vorhanden ist, wird die ursprüngliche Schnittstelle aufgerufen.
Das obige ist der detaillierte Inhalt vonVerstehen Sie das Proxy-Muster von PHP-Entwurfsmustern in einem Artikel. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!