Extension of design pattern agent pattern

Extension of design pattern agent pattern

  The previous article has introduced the agent mode briefly. This article is mainly about the agent mode.

I. General Agent Mode

The common agent is that we need to know the existence of the agent clearly, and can only access the implementation through the agent, not directly access the real implementation, such as our VPN.
We need to know the IP address of the proxy clearly. When we access the proxy server, we must access it through the proxy, but we do not need to create one ourselves.
The proxied servers, all of which are shielded for high-level access.

Realization

public interface Subject {

	void play();
}

public class RealSubject implements Subject{

	private String name;

	@Override
	public void play() {
		System.out.printf(this.name + "Start playing games");
	}

	public RealSubject(Subject proxy,String name) throws Exception {
		//It's just a simple demonstration here. Judgment conditions can be customized.
		if(proxy == null){
			throw new Exception("Cannot create real object");
		}
		this.name = name;
	}
}

public class SubjectProxy implements Subject {

	private Subject subject = null;

	public SubjectProxy(String name) throws Exception {
		this.subject = new RealSubject(this, name);
	}

	@Override
	public void play() {
		this.subject.play();
	}
}

call

public class Cliect {

	public static void main(String[] args) throws Exception {
		Subject subject = new SubjectProxy("Zhang San");
		subject.play();
	}
}

We only modify the construction method of the real implementation and block direct access to the real implementation, which can only be accessed by the agent.

II. Compulsory agency

 Generally speaking, we find real roles through agents, such as finding houses through agents. But forced agents emphasize "forced". When will this happen?
 
 For example, in a real situation, we may go to the leader to deal with a certain matter, but when you find the leader of the company, he will tell you, you go to my assistant, you try to
 A real role is created, but an agent role is generated. This is a forced agent.
 
 The agent of the force agent is specified by the real role
 

Realization

public interface Subject {

	void play();

	Subject getProxy();

}

Real agent object manages agent itself

public class RealSubject implements Subject {

	private String name;

	private Subject subject = null;

	public RealSubject(String name) {
		this.name = name;
	}

	@Override
	public Subject getProxy(){
		if(this.subject == null){
			this.subject = new SubjectProxy(this);
		}
		return this.subject;
	}

	@Override
	public void play() {
		if(this.isProxy()){
			System.out.println(this.name + "Play a game");
		}else{
			System.out.println("Please use the specified proxy to access");
		}

	}

	public boolean isProxy(){
		return this.subject != null;
	}
}
public class SubjectProxy implements Subject {
	private Subject subject = null;

	public SubjectProxy(Subject subject) {
		this.subject = subject;
	}

	@Override
	public void play() {
		this.subject.play();
	}

	@Override
	public Subject getProxy() {
		return this;
	}


}
public class Client {

	public static void main(String[] args) {
		Subject realSubject = new RealSubject("Zhang San");

		Subject proxy = realSubject.getProxy();

		proxy.play();
	}
}

III. personalized agent

In the previous examples, agents only complete the tasks that agent interfaces or agent objects can handle, but most agent objects have their own personalized interfaces, such as lawyers acting as agents.
There is a charge for

uml

IV. dynamic agency

In the implementation phase, dynamic agent does not care who the agent is, but specifies the agent object in the runtime phase, and performs relevant notifications and additions according to the characteristics of the agent object.

UML

I. simple implementation

public interface Subject {
	void play();
}

public class RealSubject implements Subject{

	private String name;

	public RealSubject(String name) {
		this.name = name;
	}

	@Override
	public void play() {
		System.out.println(this.name + "Play the game.");
	}
}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class SubjectHandler implements InvocationHandler {

	private Object target;

	public SubjectHandler(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		System.out.println("Deal with the business logic I want to add first");
		return method.invoke(target, args);
	}
}

import java.lang.reflect.Proxy;

public class Client {

	public static void main(String[] args) {
		//Represented object
		Subject subject = new RealSubject("Zhang San");

		//Proxy the methods of the proxied object. You can also understand that they are actually executed here.
		SubjectHandler subjectHandler = new SubjectHandler(subject);

		ClassLoader classLoader = subject.getClass().getClassLoader();

		//Generate dynamic proxy objects
		Subject proxyInstance = (Subject)Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, subjectHandler);

		System.out.println(subject);
		System.out.println(proxyInstance);
		proxyInstance.play();

	}
}

II. Add dynamic agent


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class DynamicProxy {

	public  static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler handler){
		return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
	}
}

public class Client {

	public static void main(String[] args) {
		Subject subject = new RealSubject("Zhang San");
		ClassLoader classLoader = subject.getClass().getClassLoader();
		Class<?>[] interfaces = subject.getClass().getInterfaces();
		MySubjectHandler mySubjectHandler = new MySubjectHandler(subject);
		Subject proxyInstance = DynamicProxy.newProxyInstance(classLoader, interfaces, mySubjectHandler);
		proxyInstance.play();
	}
	
}

III. notice of increase

public interface Advice {

	void exec();
}

public class BeforeAdvice implements Advice {

	@Override
	public void exec() {
		System.out.println("Notice processing before execution");
	}
}

Dynamic proxy

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class DynamicProxy {

	public  static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler handler){
		//Here is only the simulation condition, which can be judged according to the actual needs
		if(true){

			// Pre notification at the connection point does not affect subsequent business increase
			(new BeforeAdvice()).exec();
		}
		return (T) Proxy.newProxyInstance(classLoader, interfaces, handler);
	}
}


public class Client {

	public static void main(String[] args) {
		Subject subject = new RealSubject("Zhang San");
		ClassLoader classLoader = subject.getClass().getClassLoader();
		Class<?>[] interfaces = subject.getClass().getInterfaces();
		MySubjectHandler mySubjectHandler = new MySubjectHandler(subject);
		Subject proxyInstance = DynamicProxy.newProxyInstance(classLoader, interfaces, mySubjectHandler);
		proxyInstance.play();
	}

}

IV. dynamic agent for designated business

import java.lang.reflect.InvocationHandler;

public class SubjectDynamicProxy extends DynamicProxy {

	public static Subject newSubjectInstance(Subject subject){
	//You can add it according to the business here
		ClassLoader classLoader = subject.getClass().getClassLoader();
		Class<?>[] interfaces = subject.getClass().getInterfaces();
		InvocationHandler mySubjectHandler = new MySubjectHandler(subject);
		return newProxyInstance(classLoader, interfaces, mySubjectHandler);
	}
}

Call to modify, the code logic becomes more concise

public class Clien2 {

	public static void main(String[] args) {
		Subject subject = new RealSubject("Zhang San");
		Subject proxy = SubjectDynamicProxy.newSubjectInstance(subject);
		proxy.play();

	}
}
summary
Maybe we can't see the difference between static agent and dynamic agent from the example. In fact, the essential difference lies in the use scenario. Dynamic agent solves the problem of cross cutting programming.
Enhance or control the behavior of the proxied object without changing the existing code structure.

Keywords: Programming Java VPN

Added by alexjb on Mon, 28 Oct 2019 02:51:59 +0200