Understanding and using design patterns can cultivate our good object-oriented programming habits, and in actual applications, we can enjoy the fun of being at ease.
Proxy is a relatively useful model, and there are many variants. The application scenarios cover the large structure from a small structure to the entire system. Proxy means proxy. We may have the concept of proxy servers, etc. The concept of proxy can be explained as: from the starting point to There is an intermediate layer between the destinations, meaning agent.
Defined in Design Pattern: Provides a proxy for other objects to control access to this object.
Why use proxy mode
1. Authorization mechanism Users of different levels of authorization have different access rights to the same object. For example, in the Jive forum system, Proxy is used for authorization mechanism control. There are two types of people visiting the forum: registered user and tourists (unregistered users), and in Jive This allows you to control the access rights of these two users to the forum through a proxy like ForumProxy.
2. A client cannot operate directly to an object, but must interact with that object.
Give two specific examples:
1. If the object is a large image and it takes a long time to display it, then when the image is included in the document, use the editor or browser to open the document, and the document must be opened very quickly and cannot wait. The large image processing is completed, and at this time, an image Proxy needs to be used to replace the real image.
2. If that object is on a remote server on the Internet and directly operates this object may be slow due to network speed, then we can use Proxy to replace that object first.
In short, the principle is that for objects with high overhead, they are created only when using it. This principle can save us a lot of valuable Java memory. Therefore, some people think that Java consumes resource memory, and I think this has something to do with the programming idea.
How to use proxy mode
Taking the Jive forum system as an example, there are many types of users who visit the forum system: registered ordinary users, forum managers, system managers, and tourists. Only by registering an ordinary user can speak. Forum managers can manage their authorized forums, and system managers can manage all transactions, etc. These permission division and management are completed using Proxy.
Forum is the core interface of Jive. The main behaviors related to forum operations are displayed in Forum, such as the forum name, acquisition and modification of forum description, post post deletion and editing, etc.
Users with various levels of permissions are defined in ForumPermissions:
The code copy is as follows:
public class ForumPermissions implements Cacheable {
/**
* Permission to read object.
*/
public static final int READ = 0;
/**
* Permission to administrator the entire system.
*/
public static final int SYSTEM_ADMIN = 1;
/**
* Permission to administrator a particular forum.
*/
public static final int FORUM_ADMIN = 2;
/**
* Permission to administrator a particular user.
*/
public static final int USER_ADMIN = 3;
/**
* Permission to administrator a particular group.
*/
public static final int GROUP_ADMIN = 4;
/**
* Permission to modernate threads.
*/
public static final int MODERATE_THREADS = 5;
/**
* Permission to create a new thread.
*/
public static final int CREATE_THREAD = 6;
/**
* Permission to create a new message.
*/
public static final int CREATE_MESSAGE = 7;
/**
* Permission to modern messages.
*/
public static final int MODERATE_MESSAGES = 8;
.....
public boolean isSystemOrForumAdmin() {
return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
}
.....
}
Therefore, various operation permissions in Forum are related to the user level defined by ForumPermissions. As the implementation of the interface Forum: ForumProxy links this correspondence relationship. For example, when modifying the name of Forum, only the forum manager or system manager can modify it, the code is as follows:
The code copy is as follows:
public class ForumProxy implements Forum {
private ForumPermissions permissions;
private Forum forum;
this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization,
ForumPermissions permissions){
this.forum = forum;
this.authorization = authorization;
this.permissions = permissions;
}
.....
public void setName(String name) throws UnauthorizedException,
ForumAlreadyExistsException{
//Only the system or forum administrator can modify the name if (permissions.isSystemOrForumAdmin()) {
forum.setName(name);
}
else {
throw new UnauthorizedException();
}
}
...
}
DbForum is the real implementation of interface Forum. Take modifying the forum name as an example:
The code copy is as follows:
public class DbForum implements Forum, Cacheable {
...
public void setName(String name) throws ForumAlreadyExistsException {
....
this.name = name;
// Here you really save the new name to the database to saveToDb();
....
}
...
}
Whenever the event of modifying the forum name is involved, other programs must first deal with ForumProxy. ForumProxy decides whether they have permission to do something. ForumProxy is a veritable "gateway" and "security proxy system".
In daily applications, it is inevitable that the system authorization or security system will always be involved. Regardless of whether you use Proxy or not, you are actually using Proxy.
Let's continue to talk more deeply in combination with Jive, and the factory model will be involved below.
We already know that using Forum requires the use of ForumProxy. Creating a Forum in Jive is to use the Factory pattern, and there is a total abstract class ForumFactory. In this abstract class, calling ForumFactory is implemented through the getInstance() method, and Singleton is used here (also One of the design patterns), getInstance() returns ForumFactoryProxy.
Why not return ForumFactory, but return ForumFactory implementation ForumFactoryProxy? The reason is obvious, and it is necessary to determine whether the forum has permission to create it through the proxy.
In ForumFactoryProxy we see the code as follows:
The code copy is as follows:
public class ForumFactoryProxy extends ForumFactory {
protected ForumFactory factory;
protected Authorization authorization;
protected ForumPermissions permissions;
public ForumFactoryProxy(Authorization authorization, ForumFactory factory,ForumPermissions permissions){
this.factory = factory;
this.authorization = authorization;
this.permissions = permissions;
}
public Forum createForum(String name, String description)
throws UnauthorizedException, ForumAlreadyExistsException{
//Only system administrators can create forum
if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {
Forum newForum = factory.createForum(name, description);
return new ForumProxy(newForum, authorization, permissions);
}
else {
throw new UnauthorizedException();
}
}
}
The method createForum returns ForumProxy. Proxy is like a wall, and other programs can only interact with Proxy.
Notice that there are two Proxy here: ForumProxy and ForumFactoryProxy. Represents two different responsibilities: using Forum and creating Forum. As for why using objects is separated from creating objects, this is why the Factory pattern is used: it is for "encapsulation" and "dispatch". In other words, the functions are as single as possible to facilitate maintenance and modification.
Other post creation and use in the Jive forum system are based on the Forum idea.
Above we discussed how to use Proxy for access to the authorization mechanism. Proxy can also hide another optimization method called copy-on-write from users. Copying a huge and complex object is a very expensive operation. If there is no modification to the original object during the copying process, then such a copy overhead is unnecessary. Use a proxy to delay this copy process.
For example: We have a large collection, such as hashtable, and many clients will access it concurrently at the same time. One of the special clients needs to perform continuous data acquisition, and at this time, other clients are required to no longer add or delete things to the hashtable.
The most direct solution is: use the collection lock, let this special client obtain this lock, perform continuous data acquisition, and then release the lock.
The code copy is as follows:
public void foFetches(Hashtable ht){
synchronized(ht){
//Specific continuous data acquisition action...
}
}
However, this method may lock the Collection for a long time, and other clients will not be able to access the Collection during this period.
The second solution is to close the collection, and then let the continuous data obtain the collection operation for the clone. This solution is premised on the fact that the Collection is cloneable and there must be a method to provide a deep clone. Hashtable provides its own clone method, but not the clone of the Key and value objects.
The code copy is as follows:
public void foFetches(Hashtable ht){
Hashttable newht=(Hashtable)ht.clone();
}
The problem comes again. Since it is an object operation based on clone, if the original parent is modified by other client operations, then the operation of clone objects will be meaningless.
The final solution: We can wait until other clients have completed modification before cloneing, that is, this special client first performs a series of data acquisition operations by calling a method called clone. But in fact, no object copying was actually done until other clients modify the object collection.
Implement this solution using Proxy, which is the copy-on-write operation.
Proxy has a wide range of applications. The popular distribution calculation methods such as RMI and Corba are all applications of the Proxy mode.