Understanding and using Design patterns can cultivate our good object-oriented programming habits. At the same time, in practical applications, we can be like a fish in water and enjoy the fun of ease.
Proxy is a more useful mode, and there are many variants. The application scenarios cover small structures to large structures of the entire system. Proxy means proxy. We may have concepts such as proxy servers. The concept of proxy can The explanation is: there is an intermediate layer between the starting point and the destination, which means agency.
Design pattern definition: Provide a proxy for other objects to control access to this object.
Why use proxy mode
1. Authorization mechanism Users at different levels have different access rights to the same object. For example, in the Jive forum system, Proxy is used to control the authorization mechanism and access the forum. There are two types of people: registered users and visitors (unregistered users). Jive uses agents like ForumProxy to control the access rights of these two users to the forum.
2. A client cannot directly operate on an object, but it must interact with that object.
Two specific situations are given as examples:
1. If the object is a very large picture and it takes a long time to be displayed, then when the picture is included in the document, Use an editor or browser to open this document. The document must be opened very quickly and you cannot wait for the large image to be processed. In this case, you need to create a picture Proxy to replace the real picture.
2. If the object is on a remote server on the Internet, directly operating the object may be slow due to network speed, then we can use Proxy to replace the object first.
In short, the principle is that expensive objects should only be created when they are used. This principle can save us a lot of valuable Java memory. Therefore, some people think that Java consumes resources and memory. I think this has a certain relationship with programming ideas.
How to use the proxy mode
Take the Jive forum system as an example. There are many types of users who access the forum system: registered ordinary users, forum managers, system managers, and tourists. Only registered ordinary users can speak. Forum managers can manage the forums for which they are authorized. System managers can manage all affairs, etc. These authority divisions 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 forum name, obtaining and modifying forum description, posting, deleting and editing of posts, 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 levels defined by ForumPermissions, as the implementation of the interface Forum: ForumProxy connects this correspondence. For example, to modify the name of the Forum, only the forum administrator or system administrator can modify it. 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{ //只有是系统或论坛管理者才可以修改名称 if (permissions.isSystemOrForumAdmin()) { forum.setName(name); } else { throw new UnauthorizedException(); } } ... }
And DbForum is the real implementation of the interface Forum. Take modifying the forum name as an example:
public class DbForum implements Forum, Cacheable { ... public void setName(String name) throws ForumAlreadyExistsException { .... this.name = name; //这里真正将新名称保存到数据库中 saveToDb(); .... } ... }
When it comes to modifying the forum name, other programs must first deal with ForumProxy. ForumProxy determines whether it has the authority to do a certain thing. 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. Whether you use Proxy consciously or not, you are actually already using Proxy.
Let’s continue to talk in depth with Jive, and the following will involve the factory model.
We already know that using Forum requires ForumProxy. Creating a Forum in Jive uses Factory mode. There is a general abstract class ForumFactory. In this abstract class, calling ForumFactory is implemented through the getInstance() method. Singleton is used here (also one of the design patterns), and getInstance() returns ForumFactoryProxy.
Why not return ForumFactory, but return ForumFactory's implementation ForumFactoryProxy? The reason is obvious. You need to use a proxy to determine whether you have permission to create a forum.
In ForumFactoryProxy we see the code 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{ //只有系统管理者才可以创建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 also 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 and creating objects are separated, this is also the reason why the Factory pattern is used: to "encapsulate" and "dispatch". In other words, the functions should be as simple as possible to facilitate maintenance and modification.
The creation and use of other posts in the Jive forum system are all based on the idea of Forum.
Above we discussed how to use Proxy to access the authorization mechanism. Proxy can also hide another optimization method called copy-on-write from users. Copying a large and complex object is an expensive operation. If the original object is not modified during the copy process, then such copy overhead is unnecessary. Use a proxy to delay this copying process.
比如:我们有一个很大的Collection,具体如hashtable,有很多客户端会并发同时访问它。其中一个特别的客户端要进行连续的数据获取,此时要求其他客户端不能再向hashtable中增加或删除 东东。
最直接的解决方案是:使用collection的lock,让这特别的客户端获得这个lock,进行连续的数据获取,然后再释放lock。
public void foFetches(Hashtable ht){ synchronized(ht){ //具体的连续数据获取动作.. } }
但是这一办法可能锁住Collection会很长时间,这段时间,其他客户端就不能访问该Collection了。
第二个解决方案是clone这个Collection,然后让连续的数据获取针对clone出来的那个Collection操作。这个方案前提是,这个Collection是可clone的,而且必须有提供深度clone的方法。Hashtable就提供了对自己的clone方法,但不是Key和value对象的clone。
public void foFetches(Hashtable ht){ Hashttable newht=(Hashtable)ht.clone(); }
问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了,那么对clone出来的对象操作就没有意义了。
最后解决方案:我们可以等其他客户端修改完成后再进行clone,也就是说,这个特别的客户端先通过调用一个叫clone的方法来进行一系列数据获取操作。但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象Collection。
使用Proxy实现这个方案,这就是copy-on-write操作。
Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用。
更多Java设计模式之代理模式(Proxy模式)介绍相关文章请关注PHP中文网!
相关文章: