提供对象的替代品或其占位符。代理控制着对于原对象的访问,容许在将请求提交给对象先后进行一些处理java
在面向对象的系统中,有些对象因为某种缘由(好比对象建立的开销很大,或者某些操做须要安全控制,或者须要进程外的访问等),直接访问对象会给使用者或者系统结构带来不少麻烦 api
代理会将全部获取了指向服务对象或其结果的客户端记录在案。代理会时不时地遍历各个客户端,检查它们是否仍在运行。若是相应的客户端列表为空,代理就会销毁该服务对象,释放底层系统资源。代理还能够记录客户端是否修改了服务对象。其余客户端还能够复用未修改的对象缓存
1)能够在客户端毫无察觉的状况下控制服务对象安全
2)客户端对服务对象的生命周期没有特殊要求, 你能够对生命周期进行管理服务器
3)开闭原则。 你能够在不对服务或客户端作出修改的状况下建立新代理网络
4)Proxy模式能够对用户隐藏另外一种称为copy-on-write的优化方式,该优化与根据须要建立对象有关。拷贝一个庞大而复杂的对象是一种开销很大的操做,若是这个拷贝并无被修改,那么开销就没有必要。能够用代理延迟这一拷贝过程。在实现copy-on-write时必须对实体进行引用计数。只有当用户请求一个修改该实体的操做时,代理才会真正的拷贝它。此时,代理须要减小实体引用计数,当引用数目为零时,这个实体将被删除app
5)服务响应可能会延迟 less
some_cool_media_library/ThirdPartyYouTubeLib.java: 远程服务接口 dom
package proxy.some_cool_media_library; import java.util.HashMap; /** * @author GaoMing * @date 2021/7/20 - 19:25 */ public interface ThirdPartyYouTubeLib { HashMap<String, Video> popularVideos(); Video getVideo(String videoId); }
some_cool_media_library/ThirdPartyYouTubeClass.java: 远程服务实现ide
package proxy.some_cool_media_library; import java.util.HashMap; /** * @author GaoMing * @date 2021/7/20 - 19:22 */ public class ThirdPartyYouTubeClass implements ThirdPartyYouTubeLib{ @Override public HashMap<String, Video> popularVideos() { connectToServer("http://www.youtube.com"); return getRandomVideos(); } @Override public Video getVideo(String videoId) { connectToServer("http://www.youtube.com/" + videoId); return getSomeVideo(videoId); } // ----------------------------------------------------------------------- // Fake methods to simulate network activity. They as slow as a real life. private int random(int min, int max) { return min + (int) (Math.random() * ((max - min) + 1)); } private void experienceNetworkLatency() { int randomLatency = random(5, 10); for (int i = 0; i < randomLatency; i++) { try { Thread.sleep(100); } catch (InterruptedException ex) { ex.printStackTrace(); } } } private void connectToServer(String server) { System.out.print("Connecting to " + server + "... "); experienceNetworkLatency(); System.out.print("Connected!" + "\n"); } private HashMap<String, Video> getRandomVideos() { System.out.print("Downloading populars... "); experienceNetworkLatency(); HashMap<String, Video> hmap = new HashMap<String, Video>(); hmap.put("catzzzzzzzzz", new Video("sadgahasgdas", "Catzzzz.avi")); hmap.put("mkafksangasj", new Video("mkafksangasj", "Dog play with ball.mp4")); hmap.put("dancesvideoo", new Video("asdfas3ffasd", "Dancing video.mpq")); hmap.put("dlsdk5jfslaf", new Video("dlsdk5jfslaf", "Barcelona vs RealM.mov")); hmap.put("3sdfgsd1j333", new Video("3sdfgsd1j333", "Programing lesson#1.avi")); System.out.print("Done!" + "\n"); return hmap; } private Video getSomeVideo(String videoId) { System.out.print("Downloading video... "); experienceNetworkLatency(); Video video = new Video(videoId, "Some video title"); System.out.print("Done!" + "\n"); return video; } }
some_cool_media_library/Video.java: 视频文件
package proxy.some_cool_media_library; /** * @author GaoMing * @date 2021/7/20 - 19:22 */ public class Video { public String id; public String title; public String data; Video(String id, String title) { this.id = id; this.title = title; this.data = "Random video."; } }
proxy/YouTubeCacheProxy.java: 缓存代理
package proxy.proxy; import proxy.some_cool_media_library.ThirdPartyYouTubeClass; import proxy.some_cool_media_library.ThirdPartyYouTubeLib; import proxy.some_cool_media_library.Video; import java.util.HashMap; /** * @author GaoMing * @date 2021/7/20 - 19:23 */ public class YouTubeCacheProxy implements ThirdPartyYouTubeLib{ private ThirdPartyYouTubeLib youtubeService; private HashMap<String, Video> cachePopular = new HashMap<String, Video>(); private HashMap<String, Video> cacheAll = new HashMap<String, Video>(); public YouTubeCacheProxy() { this.youtubeService = new ThirdPartyYouTubeClass(); } @Override public HashMap<String, Video> popularVideos() { if (cachePopular.isEmpty()) { cachePopular = youtubeService.popularVideos(); } else { System.out.println("Retrieved list from cache."); } return cachePopular; } @Override public Video getVideo(String videoId) { Video video = cacheAll.get(videoId); if (video == null) { video = youtubeService.getVideo(videoId); cacheAll.put(videoId, video); } else { System.out.println("Retrieved video '" + videoId + "' from cache."); } return video; } public void reset() { cachePopular.clear(); cacheAll.clear(); } }
downloader/YouTubeDownloader.java: 媒体下载应用
package proxy.downloader; import proxy.some_cool_media_library.ThirdPartyYouTubeLib; import proxy.some_cool_media_library.Video; import java.util.HashMap; /** * @author GaoMing * @date 2021/7/20 - 19:23 */ public class YouTubeDownloader { private ThirdPartyYouTubeLib api; public YouTubeDownloader(ThirdPartyYouTubeLib api) { this.api = api; } public void renderVideoPage(String videoId) { Video video = api.getVideo(videoId); System.out.println("\n-------------------------------"); System.out.println("Video page (imagine fancy HTML)"); System.out.println("ID: " + video.id); System.out.println("Title: " + video.title); System.out.println("Video: " + video.data); System.out.println("-------------------------------\n"); } public void renderPopularVideos() { HashMap<String, Video> list = api.popularVideos(); System.out.println("\n-------------------------------"); System.out.println("Most popular videos on YouTube (imagine fancy HTML)"); for (Video video : list.values()) { System.out.println("ID: " + video.id + " / Title: " + video.title); } System.out.println("-------------------------------\n"); } }
Demo.java: 初始化代码
package proxy; import proxy.downloader.YouTubeDownloader; import proxy.proxy.YouTubeCacheProxy; import proxy.some_cool_media_library.ThirdPartyYouTubeClass; /** * @author GaoMing * @date 2021/7/20 - 19:21 */ public class Demo { public static void main(String[] args) { YouTubeDownloader naiveDownloader = new YouTubeDownloader(new ThirdPartyYouTubeClass()); YouTubeDownloader smartDownloader = new YouTubeDownloader(new YouTubeCacheProxy()); long naive = test(naiveDownloader); long smart = test(smartDownloader); System.out.print("Time saved by caching proxy: " + (naive - smart) + "ms"); } private static long test(YouTubeDownloader downloader) { long startTime = System.currentTimeMillis(); // User behavior in our app: downloader.renderPopularVideos(); downloader.renderVideoPage("catzzzzzzzzz"); downloader.renderPopularVideos(); downloader.renderVideoPage("dancesvideoo"); // Users might visit the same page quite often. downloader.renderVideoPage("catzzzzzzzzz"); downloader.renderVideoPage("someothervid"); long estimatedTime = System.currentTimeMillis() - startTime; System.out.print("Time elapsed: " + estimatedTime + "ms\n"); return estimatedTime; } }
执行结果
Connecting to http://www.youtube.com... Connected! Downloading populars... Done! ------------------------------- Most popular videos on YouTube (imagine fancy HTML) ID: sadgahasgdas / Title: Catzzzz.avi ID: asdfas3ffasd / Title: Dancing video.mpq ID: 3sdfgsd1j333 / Title: Programing lesson#1.avi ID: mkafksangasj / Title: Dog play with ball.mp4 ID: dlsdk5jfslaf / Title: Barcelona vs RealM.mov ------------------------------- Connecting to http://www.youtube.com/catzzzzzzzzz... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: catzzzzzzzzz Title: Some video title Video: Random video. ------------------------------- Connecting to http://www.youtube.com... Connected! Downloading populars... Done! ------------------------------- Most popular videos on YouTube (imagine fancy HTML) ID: sadgahasgdas / Title: Catzzzz.avi ID: asdfas3ffasd / Title: Dancing video.mpq ID: 3sdfgsd1j333 / Title: Programing lesson#1.avi ID: mkafksangasj / Title: Dog play with ball.mp4 ID: dlsdk5jfslaf / Title: Barcelona vs RealM.mov ------------------------------- Connecting to http://www.youtube.com/dancesvideoo... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: dancesvideoo Title: Some video title Video: Random video. ------------------------------- Connecting to http://www.youtube.com/catzzzzzzzzz... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: catzzzzzzzzz Title: Some video title Video: Random video. ------------------------------- Connecting to http://www.youtube.com/someothervid... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: someothervid Title: Some video title Video: Random video. ------------------------------- Time elapsed: 9354ms Connecting to http://www.youtube.com... Connected! Downloading populars... Done! ------------------------------- Most popular videos on YouTube (imagine fancy HTML) ID: sadgahasgdas / Title: Catzzzz.avi ID: asdfas3ffasd / Title: Dancing video.mpq ID: 3sdfgsd1j333 / Title: Programing lesson#1.avi ID: mkafksangasj / Title: Dog play with ball.mp4 ID: dlsdk5jfslaf / Title: Barcelona vs RealM.mov ------------------------------- Connecting to http://www.youtube.com/catzzzzzzzzz... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: catzzzzzzzzz Title: Some video title Video: Random video. ------------------------------- Retrieved list from cache. ------------------------------- Most popular videos on YouTube (imagine fancy HTML) ID: sadgahasgdas / Title: Catzzzz.avi ID: asdfas3ffasd / Title: Dancing video.mpq ID: 3sdfgsd1j333 / Title: Programing lesson#1.avi ID: mkafksangasj / Title: Dog play with ball.mp4 ID: dlsdk5jfslaf / Title: Barcelona vs RealM.mov ------------------------------- Connecting to http://www.youtube.com/dancesvideoo... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: dancesvideoo Title: Some video title Video: Random video. ------------------------------- Retrieved video 'catzzzzzzzzz' from cache. ------------------------------- Video page (imagine fancy HTML) ID: catzzzzzzzzz Title: Some video title Video: Random video. ------------------------------- Connecting to http://www.youtube.com/someothervid... Connected! Downloading video... Done! ------------------------------- Video page (imagine fancy HTML) ID: someothervid Title: Some video title Video: Random video. ------------------------------- Time elapsed: 5875ms Time saved by caching proxy: 3479ms
java.lang.reflect.Proxy
识别方法:代理模式会将全部实际
工做委派给一些其余对象。除非代理是某个服务的子类,不然每一个代理方法最后都应该引用一个服务对象