Introduction to Proxy pattern of Java design pattern

  • 2020-04-01 03:41:57
  • OfStack

By understanding and using design patterns, we can develop good object-oriented programming habits, and at the same time, we can enjoy the fun in practice.

Proxy is a more useful model, and there are many variations, application occasions cover from small structure to the whole system of the large structure, Proxy is the meaning of Proxy, we may have the concept of Proxy server, Proxy concept can be explained as: there is a middle layer between the starting point to the destination, meaning Proxy.

Design pattern: provides a proxy for other objects to control access to this object.

Why use the proxy pattern

1. Authorization mechanisms at different levels of user access to the same object with different rights, such as Jive BBS system, use the Proxy authorization control, access to the BBS has two kinds of people: registered users and visitors (not a registered user), through a similar Jive ForumProxy such agents to control the two users access to the BBS.
2. A client cannot directly manipulate an object, but must interact with that object.

Two specific examples are given:

1. If the object is a is a lot of pictures, it takes a very long time to display, so when the picture is included in the document, use the editor or the browser to open this document, open the document must be quickly, can't wait for the big picture processing is completed, then you need to do a picture Proxy instead of real images.
2. If the object is on a remote server on the Internet, the direct operation of the object may be slow due to the network speed, then we can use Proxy to replace the object.

The bottom line is that we can save a lot of valuable Java memory by creating expensive objects only when they are used. Therefore, some people think that Java consumes resources of memory, and I think this has something to do with programming thinking.

How to use the proxy pattern

Taking Jive forum system as an example, there are many types of users accessing the forum system: registered ordinary users, forum administrators, system administrators, and tourists. Registered ordinary users can speak, the forum manager can manage his authorized forum, the system manager can manage all transactions, and so on, these rights division and management is done by Proxy.

Forum is the core interface of Jive, in which the main behaviors about Forum operation are displayed, such as Forum name, Forum description acquisition and modification, post deletion and editing, etc.

Users with various levels of permissions are defined in ForumPermissions:


public class ForumPermissions implements Cacheable {
/**
* Permission to read object.
*/
public static final int READ = 0; /**
* Permission to administer the entire sytem.
*/
public static final int SYSTEM_ADMIN = 1; /**
* Permission to administer a particular forum.
*/
public static final int FORUM_ADMIN = 2; /**
* Permission to administer a particular user.
*/
public static final int USER_ADMIN = 3; /**
* Permission to administer a particular group.
*/
public static final int GROUP_ADMIN = 4; /**
* Permission to moderate 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 moderate messages.
*/
public static final int MODERATE_MESSAGES = 8; ..... public boolean isSystemOrForumAdmin() {
 return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
} ..... }

Therefore, the various operation permissions in Forum are related to the user level defined by ForumPermissions, which is the implementation of interface Forum: ForumProxy is exactly the correlation. For example, change the name of Forum, only the Forum manager or system manager can change, the code 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 system or forum administrators can change the name
  if (permissions.isSystemOrForumAdmin()) {
   forum.setName(name);
  }
  else {
   throw new UnauthorizedException();
  }
    }
    ... }

DbForum is the real implementation of interface Forum, to change the name of the Forum as an example:


public class DbForum implements Forum, Cacheable {
    ...
    public void setName(String name) throws ForumAlreadyExistsException {
  ....
  this.name = name;
  //Here you actually save the new name to the database
  saveToDb();
  ....
    }
    ...
}

When it comes to modifying the forum name, other programs have to deal with ForumProxy first. ForumProxy decides whether it has the right to do something or not. ForumProxy is a veritable "gateway", "security proxy system".

In everyday applications, it is inevitable to involve the authorization or security system. Whether you unconsciously use Proxy, you are already using Proxy.

Let's go a little further with Jive and get into factory mode.

We already know that the use of Forum requires the use of ForumProxy. In Jive, a Forum is created by using the Factory pattern, and there is a general abstract class ForumFactory. In this abstract class, the call to ForumFactory is realized by the method getInstance(), where Singleton is used (also one of the design patterns), and getInstance() returns ForumFactoryProxy.

Why not return ForumFactory and return ForumFactoryProxy, the implementation of ForumFactory? The reason is obvious, and you need to determine whether you have permission to create forum through the proxy.

In ForumFactoryProxy, we can see the following code:


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 a ForumProxy, which is like a wall, and other programs can only interact with it.

Notice that there are two proxies: ForumProxy and ForumFactoryProxy. Represents two different responsibilities: using Forum and creating Forum. As for why objects are used and created separately, this is why the Factory pattern is used: to "encapsulate" and "dispatch". In other words, as much as possible, the function of a single, easy to maintain and modify.

Other parts of the Jive Forum system, such as the creation and use of posts, follow the Forum approach.

Above we discussed how Proxy can be used for authorization mechanism access. Proxy can also hide another optimization called copy-on-write from users. Copying a large and complex object is an expensive operation, and this copying overhead is not necessary if the original object is not modified during the copying process. Delay the copying process with an agent.

For example, we have a large Collection, such as hashtable, which is accessed concurrently by many clients. One particular client performs a continuous data fetch, requiring the other clients not to add or remove items to the hashtable.

The most straightforward solution is to use the collection lock, let this particular client get the lock, do continuous data acquisition, and then release the lock.


public void foFetches(Hashtable ht){
 synchronized(ht){
  //Specific continuous data acquisition action.. < br / >  }
}

However, this approach may lock the Collection for a long time, during which time other clients cannot access the Collection.

The second solution is to clone the Collection and then have the continuous data fetch the operation against the Collection that comes out of the clone. This scenario assumes that the Collection is clone, and that there must be a way to provide deep clone. Hashtable provides a clone method for itself, but not for the Key and value objects.


public void foFetches(Hashtable ht){
 Hashttable newht=(Hashtable)ht.clone();
}

The problem is that since it is an operation on a clone object, the operation on a clone object is meaningless if the original matrix is modified by other client operations.

Final solution: we can wait for the other client to complete the modification before clone, that is, this particular client first performs a series of data retrieval operations by calling a method called clone. But there is no actual copying of the object until another client modifies the object Collection.

Using the Proxy to implement the scheme, this is the copy-on-write operation.

Proxy has a wide range of applications. The popular distributed computing methods such as RMI and Corba are all applications of the Proxy pattern.


Related articles: