代理模式(学习笔记)
1. 意图
提供对象的替代品或其占位符。代理控制着对于原对象的访问,允许在将请求提交给对象前后进行一些处理
2. 动机
在面向对象的系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问对象会给使用者或者系统结构带来很多麻烦
3. 适用性
- 延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式
- 访问控制(保护代理)。如果只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序(包括恶意程序),此时可使用代理模式
- 本地执行远程服务 (远程代理)。适用于服务对象位于远程服务器上的情形。代理通过网络传递客户端请求,负责处理所有与网络相关的复杂细节
- 记录日志请求(日志记录代理)。适用于当你需要保存对于服务对象的请求历史记录时。代理可以在向服务传递请求前进行记录
- 缓存请求结果 (缓存代理)。适用于需要缓存客户请求结果并对缓存生命周期进行管理时,特别是当返回结果的体积非常大时。代理可对重复请求所需的相同结果进行缓存,还可使用请求参数作为索引缓存的键值
- 智能引用。可在没有客户端使用某个重量级对象时立即销毁该对象。
代理会将所有获取了指向服务对象或其结果的客户端记录在案。代理会时不时地遍历各个客户端,检查它们是否仍在运行。如果相应的客户端列表为空,代理就会销毁该服务对象,释放底层系统资源。代理还可以记录客户端是否修改了服务对象。其他客户端还可以复用未修改的对象
4. 结构
5. 效果
1)可以在客户端毫无察觉的情况下控制服务对象
2)客户端对服务对象的生命周期没有特殊要求, 你可以对生命周期进行管理
3)开闭原则。 你可以在不对服务或客户端做出修改的情况下创建新代理
4)Proxy模式可以对用户隐藏另一种称为copy-on-write的优化方式,该优化与根据需要创建对象有关。拷贝一个庞大而复杂的对象是一种开销很大的操作,如果这个拷贝并没有被修改,那么开销就没有必要。可以用代理延迟这一拷贝过程。在实现copy-on-write时必须对实体进行引用计数。只有当用户请求一个修改该实体的操作时,代理才会真正的拷贝它。此时,代理需要减少实体引用计数,当引用数目为零时,这个实体将被删除
5)服务响应可能会延迟
6. 代码实现
some_cool_media_library/ThirdPartyYouTubeLib.java: 远程服务接口
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: 远程服务实现
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.aviID: asdfas3ffasd / Title: Dancing video.mpqID: 3sdfgsd1j333 / Title: Programing lesson#1.aviID: mkafksangasj / Title: Dog play with ball.mp4ID: dlsdk5jfslaf / Title: Barcelona vs RealM.mov-------------------------------Connecting to http://www.youtube.com/catzzzzzzzzz... Connected!Downloading video... Done!-------------------------------Video page (imagine fancy HTML)ID: catzzzzzzzzzTitle: Some video titleVideo: Random video.-------------------------------Connecting to http://www.youtube.com... Connected!Downloading populars... Done!-------------------------------Most popular videos on YouTube (imagine fancy HTML)ID: sadgahasgdas / Title: Catzzzz.aviID: asdfas3ffasd / Title: Dancing video.mpqID: 3sdfgsd1j333 / Title: Programing lesson#1.aviID: mkafksangasj / Title: Dog play with ball.mp4ID: dlsdk5jfslaf / Title: Barcelona vs......原文转载:http://www.shaoqun.com/a/900493.html
跨境电商:https://www.ikjzd.com/
美菜:https://www.ikjzd.com/w/1874
一淘比价网:https://www.ikjzd.com/w/1698
心怡:https://www.ikjzd.com/w/1327
1.意图 提供对象的替代品或其占位符。代理控制着对于原对象的访问,允许在将请求提交给对象前后进行一些处理 2.动机 在面向对象的系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问对象会给使用者或者系统结构带来很多麻烦 3.适用性延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可
blackbird:https://www.ikjzd.com/w/950
游客遭"保证金" 没下落 旅行社"失联"追讨不易:http://www.30bags.com/a/417870.html
游客最满意vs最不满意国家榜单出炉:http://www.30bags.com/a/418007.html
游览稻城亚丁秋季必备衣物 :http://www.30bags.com/a/412484.html
游览河南云台山秘笈 - :http://www.30bags.com/a/407541.html
第一次玩交换真实经历 不带套交换真实感受:http://lady.shaoqun.com/a/247065.html
喜欢让人㖭我下面啊 女人口述被亲下面的感觉:http://www.30bags.com/m/a/249841.html
舌尖分开她的细缝舔舐 他的舌尖在她的小核上逗弄:http://www.30bags.com/m/a/249712.html
2021泰国哪里好玩 泰国哪些地方好玩 :http://www.30bags.com/a/527697.html
洗澡时,下面的头发总是容易脱落,正常吗?或者有四种危害需要注意:http://lady.shaoqun.com/a/436502.html
女人要明白,男人越爱你,睡觉时这六个"小把戏"就越频繁!:http://lady.shaoqun.com/a/436503.html
HPV阳性=宫颈癌?女性必须了解这些知识:http://lady.shaoqun.com/a/436504.html
Comments
Post a Comment