Heim  >  Artikel  >  Java  >  Beispielerklärung eines Proxy-Musters im Java-Entwurfsmuster

Beispielerklärung eines Proxy-Musters im Java-Entwurfsmuster

黄舟
黄舟Original
2017-09-28 09:24:181607Durchsuche

Der folgende Editor bringt Ihnen einen Artikel über Java-Design-Muster-Agent-Muster (Erklärung mit Beispielen). Der Herausgeber findet es ziemlich gut, deshalb teile ich es jetzt mit Ihnen und gebe es als Referenz. Folgen wir dem Editor und werfen wir einen Blick darauf

Das Proxy-Muster ist eines der häufigsten Entwurfsmuster in Java. Springs AOP verwendet den Proxy-Modus.

Im Allgemeinen werden Proxy-Modi in zwei Typen unterteilt: statischer Proxy und dynamischer Proxy.

Als Entwurfsmuster für Strukturklassen besteht seine Funktion darin, die Klasse zu erweitern, ohne den internen Code der Klasse zu ändern, was eine Ergänzung zum Vererbungsmechanismus darstellt.

Beispiel: Lassen Sie uns den Proxy-Modus am Beispiel der Benutzeranmeldung implementieren.

Die Grundvoraussetzung besteht darin, die Anmelde- und Spitznamenänderungsfunktionen des Benutzers zu realisieren.

Code oben, zuerst die IUser-Schnittstelle und die Benutzerimplementierungsklasse


public interface IUser {
 //登录
 void login(String userId,String password);
 //修改昵称
 void editNickname(String nickname);

}


public class User implements IUser {
 
 private String nickname;
 private String userId;
 private String password;
 
 public User(String userId,String password){
  this.userId = userId;
  this.password = password;
 }

 @Override
 public void login(String userId, String password){
  if(this.userId == userId && this.password == password){
   System.out.println("用户登录成功");
  }
  else
   System.out.println("用户登录失败");
 }

 @Override
 public void editNickname(String nickname) {
  this.nickname = nickname;
  System.out.println("修改昵称成功,当前用户的昵称是:"+this.nickname);
 }

}

Client-Klasse


public class Client {
 public static void main(String[] args) {
  //不调用代理模式时
  IUser user = new User("firs","123");
  user.login("firs", "123");
  user.editNickname("大风");
}

Es ist immer noch ganz einfach. Aber später teilt Ihnen der Produktmanager mit, dass wir eine Funktion zur Aufzeichnung des Benutzerverhaltens hinzufügen müssen. Was sollen wir jetzt tun? Benutzerklasse direkt ändern? Nein, nein, nein, verwenden Sie den Proxy-Modus.

Fügen Sie einfach eine Proxy-Klasse hinzu und schreiben Sie die Funktion „Benutzerverhalten aufzeichnen“ in die Proxy-Klasse. Ändern Sie die Klasse nicht, sondern erweitern Sie sie nur, um Fehler zu reduzieren.


import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 静态代理类必须实现接口,而且需要新创建一个类的代码出来
 * @author Administrator
 *
 */
public class StaticProxy implements IUser {
 private IUser user;
 public StaticProxy(String userId,String password){
  this.user = new User(userId,password);
 }
 
 //登陆前的操作,记录当前登录的时间
 void noteLoginInfo(String[] params, String opreate){
  Map<String,Object> loginInfo = new HashMap<>();
  loginInfo.put("params", params);
  loginInfo.put("opreate", opreate);
  loginInfo.put("opreateTime", new Date());
  System.out.println("记录用户操作成功");
 }
 
 @Override
 public void login(String userId, String password){
  
  noteLoginInfo(new String[]{userId, password},"login");
  
  user.login(userId, password);
 }

 @Override
 public void editNickname(String nickname) {
  noteLoginInfo(new String[]{nickname},"editNickname");
  user.editNickname(nickname);
 }

}

Client-Klasse:


public class Client {
 public static void main(String[] args) {
  //不调用代理模式时
  IUser user = new User("firs","123");
  user.login("firs", "123");
  user.editNickname("大风");
  
  System.out.println("");
  System.out.println("=============调用静态代理模式后===========");
  
  //需要实现记录用户登录和修改昵称操作的日志功能
  //基于“拓展开发,修改关闭”的设计准则,我们可以用静态代理的方式
  IUser proxy = new StaticProxy("firs","123");
  proxy.login("firs", "123");
  proxy.editNickname("我还是大风"); 

}

Auf diese Weise müssen Sie nur den Client ändern Klasse und Hinzufügen eines statischen Proxys ist ausreichend, perfekte Implementierung. Aber die Nachfrage ist endlos. „Wir haben eine Administratorrolle und einen Administrator der zweiten Ebene hinzugefügt.

Das ist jedes Mal peinlich. Ein statischer Proxy.“ Für jeden Charakter muss eine Klasse erstellt werden, und die Klassen werden explodieren. Keine Sorge, wir haben den dynamischen Proxy-Modus.

Der dynamische Proxy-Modus besteht darin, dass Sie nicht selbst eine neue Proxy-Klasse erstellen müssen. Sie übergeben ihm die spezifische Implementierungsklasse (Subjekt) und es wird standardmäßig eine Proxy-Klasse für Sie generiert.

Im Wesentlichen nutzt es den Reflexionsmechanismus von Java, um die entsprechende Proxy-Klasse zur Laufzeit dynamisch zu generieren.

Ohne Reflexion gibt es keinen dynamischen Proxy.


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 动态代理类不用和主体类继承同一个接口
 * @author Administrator
 *
 */
public class DynamicProxy implements InvocationHandler {
 private Object object;
 public DynamicProxy(String userId,String password,Class<?> c){
  Object obj = null;
  try {
   obj = Class.forName(c.getName())
     .getConstructor(String.class,String.class)
     .newInstance(userId,password);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  this.object = obj;
 }
 
 //登陆前的操作,记录当前登录的时间
 void noteLoginInfo(String[] params, String opreate){
  Map<String,Object> loginInfo = new HashMap<>();
  loginInfo.put("params", params);
  loginInfo.put("opreate", opreate);
  loginInfo.put("opreateTime", new Date());
  System.out.println("记录用户操作成功");
 }

 @Override
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  String[] params = new String[args.length];
  for(int i = 0 ;i < args.length ; i++){
   params[i] = args[i].toString();
  }
  noteLoginInfo(params, method.getName());
  return method.invoke(object, args);
 }

}

Die letzte Client-Klasse:


package com.test.my;

import java.lang.reflect.Proxy;


public class Client {
 public static void main(String[] args) {
  //不调用代理模式时
  IUser user = new User("firs","123");
  user.login("firs", "123");
  user.editNickname("大风");
  
  System.out.println("");
  System.out.println("=============调用静态代理模式后===========");
  
  //需要实现记录用户登录和修改昵称操作的日志功能
  //基于“拓展开发,修改关闭”的设计准则,我们可以用静态代理的方式
  IUser proxy = new StaticProxy("firs","123");
  proxy.login("firs", "123");
  proxy.editNickname("我还是大风");
  
  System.out.println("");
  System.out.println("=============调用动态代理模式后===========");
  
  DynamicProxy dynamicProxy = new DynamicProxy("firs","123",Admin.class);
  
  ClassLoader cl = Admin.class.getClassLoader();
  IUser iuser = (IUser)Proxy.newProxyInstance(cl,
        new Class[]{IUser.class}, dynamicProxy);
  iuser.login("firs","123");
  iuser.editNickname("使用动态代理后的大风");
  
 }

}

Admin-Klasse aufgrund der Nachfrage hinzugefügt


public class Admin implements IUser {
 
 private String nickname;
 private String userId;
 private String password;
 
 public Admin(String userId,String password){
  this.userId = userId;
  this.password = password;
 }

 @Override
 public void login(String userId, String password){
  if(this.userId == userId && this.password == password){
   System.out.println("用户登录成功");
  }
  else
   System.out.println("用户登录失败");
 }

 @Override
 public void editNickname(String nickname) {
  this.nickname = nickname;
  System.out.println("修改昵称成功,当前用户的昵称是:"+this.nickname);
 }

}

Zusammenfassung:

1. Der statische Proxy-Modus ist relativ einfach, der Hauptpunkt ist Erstellen eine neue Proxy-Klasse für jede Implementierungsklasse (Subjektkörper), die einen Verweis auf die Entitätsklasse (Subjektkörper) hat, sodass die Kontrolle über die ursprüngliche Implementierungsklasse (Subjektkörper) erreicht werden kann, einschließlich AOP-Steuerung usw.

2. Statischer Proxy hat möglicherweise Einschränkungen. Es kann erforderlich sein, für jede Entitätsklasse eine neue statische Proxy-Klasse zu erstellen.

3. Der dynamische Proxy ist nicht auf die spezifische Implementierungsklasse (Subjektkörper) beschränkt. Er verwendet intern ein Objekt, um auf die Referenz der Entitätsklasse zuzugreifen, und verwendet dann die Reflektion, um verschiedene Methoden der Entitätsklasse abzurufen. Dadurch wird die aspektorientierte AOP-Programmiersteuerung der Klasse (Subjektkörper) implementiert.

4. Die obige Schreibmethode ist ein dynamischer Proxy im JDK, der nicht perfekt ist, da diese Art von dynamischem Proxy erfordert, dass die Entitätsklasse mindestens eine Schnittstelle implementiert. Das Problem besteht darin, dass nicht alle Klassen über Schnittstellen verfügen, daher ist es hier nicht perfekt.

Das obige ist der detaillierte Inhalt vonBeispielerklärung eines Proxy-Musters im Java-Entwurfsmuster. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn