Maison > Java > javaDidacticiel > Exemple d'explication du modèle de proxy dans le modèle de conception Java

Exemple d'explication du modèle de proxy dans le modèle de conception Java

黄舟
Libérer: 2017-09-28 09:24:18
original
1669 Les gens l'ont consulté

L'éditeur suivant vous apportera un article sur le modèle de conception-agent Java (explication avec exemples). L'éditeur le trouve plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence pour tout le monde. Suivons l'éditeur et jetons un coup d'œil

Le modèle de proxy est l'un des modèles de conception les plus courants en Java. L'aop de Spring utilise le mode proxy.

De manière générale, les modes proxy sont divisés en deux types : proxy statique et proxy dynamique.

En tant que modèle de conception pour les classes structurelles, sa fonction est d'étendre la classe sans modifier le code interne de la classe, ce qui est un complément au mécanisme d'héritage.

par exemple : implémentons le mode proxy en utilisant l'exemple de connexion utilisateur.

L'exigence de base est la suivante : réaliser les fonctions de connexion et de modification du pseudo de l'utilisateur.

Code ci-dessus, d'abord l'interface IUser et la classe d'implémentation utilisateur


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

}
Copier après la connexion


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);
 }

}
Copier après la connexion

Classe client


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

C'est quand même très simple. Mais plus tard, le chef de produit vous dit que nous devons ajouter une fonction pour enregistrer le comportement des utilisateurs. Que devons-nous faire maintenant ? Modifier directement la classe d'utilisateurs ? Non, non, non, utilisez le mode proxy.

Ajoutez simplement une classe proxy et écrivez la fonction "d'enregistrement du comportement de l'utilisateur" dans la classe proxy. Ne modifiez pas la classe, étendez simplement la classe pour réduire les erreurs.


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);
 }

}
Copier après la connexion

Classe client :


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("我还是大风"); 

}
Copier après la connexion

De cette façon, il vous suffit de modifier le client classe et ajouter un proxy statique suffit, implémentation parfaite. Mais la demande est infinie. Le chef de produit vous dit : "Nous avons ajouté un rôle d'administrateur, et un administrateur de deuxième niveau." Il y a beaucoup de rôles,

C'est gênant, à chaque fois. Un proxy statique. la classe doit être construite pour chaque personnage, et les classes vont exploser. Ne vous inquiétez pas, nous avons le mode proxy dynamique.

Le mode proxy dynamique signifie que vous n'avez pas besoin de créer vous-même une nouvelle classe proxy. Vous lui transmettez la classe d'implémentation spécifique (sujet), et il générera une classe proxy pour vous par défaut.

Essentiellement, il utilise le mécanisme de réflexion de Java pour générer dynamiquement la classe proxy correspondante au moment de l'exécution.

Sans réflexion, il n'y a pas de proxy dynamique.


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);
 }

}
Copier après la connexion

La dernière classe client :


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("使用动态代理后的大风");
  
 }

}
Copier après la connexion

Classe d'administrateur ajoutée en raison de la demande


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);
 }

}
Copier après la connexion

Résumé :

1 Le mode proxy statique est relativement simple, le point principal est Créer. une nouvelle classe proxy pour chaque classe d'implémentation (corps du sujet), qui a une référence à la classe d'entité (corps du sujet), de sorte que le contrôle de la classe d'implémentation d'origine (corps du sujet) puisse être réalisé, y compris le contrôle AOP, etc.

2. Le proxy statique a des limites. Il peut être nécessaire de créer une nouvelle classe proxy statique pour chaque classe d'entité. Cela peut entraîner la création d'un trop grand nombre de classes proxy statiques.

3. Le proxy dynamique ne se limite pas à la classe d'implémentation spécifique (corps du sujet). En interne, il utilise un objet pour accéder à la référence de la classe d'entité, puis utilise la réflexion pour obtenir diverses méthodes de la classe d'entité. réalisant ainsi le contrôle de programmation AOP orienté aspect de la classe (corps du sujet).

4. La méthode d'écriture ci-dessus est un proxy dynamique dans JDK, ce qui n'est pas parfait car ce type de proxy dynamique nécessite que la classe d'entité implémente au moins une interface. Le problème est que toutes les classes n'auront pas d'interfaces, donc ce n'est pas parfait ici.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal