代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
介绍
- 意图:为其他对象提供一种代理以控制对这个对象的访问。
- 代理模式的主要优点有:
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
- 代理对象可以扩展目标对象的功能;
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;
- 其主要缺点是:
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
- 增加了系统的复杂度;
- 应用实例: 1、买火车票不一定在火车站买,也可以去代售点。 2、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。 3、spring aop。
- 使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
实现
我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage 对象加载的内存占用。
ProxyPatternDemo 类使用 ProxyImage 来获取要加载的 Image 对象,并按照需求进行显示。
代理模式的 UML 图
java
步骤 1
创建一个接口。
Image.java
public interface Image { void display(); }
步骤 2
创建实现接口的实体类。
RealImage.java
public class RealImage implements Image { private String fileName; public RealImage(String fileName){ this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("Displaying " + fileName); } private void loadFromDisk(String fileName){ System.out.println("Loading " + fileName); } }
ProxyImage.java
public class ProxyImage implements Image{ private RealImage realImage; private String fileName; public ProxyImage(String fileName){ this.fileName = fileName; } @Override public void display() { if(realImage == null){ realImage = new RealImage(fileName); } realImage.display(); } }
步骤 3
当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。
ProxyPatternDemo.java
public class ProxyPatternDemo { public static void main(String[] args) { Image image = new ProxyImage("test_10mb.jpg"); // 图像将从磁盘加载 image.display(); System.out.println(""); // 图像不需要从磁盘加载 image.display(); } }
步骤 4
执行程序,输出结果:
Loading test_10mb.jpg Displaying test_10mb.jpg Displaying test_10mb.jpg
rust
rust和java的搭建过程类似,如就不再赘述rust搭建过程。
trait Image { fn dispaly(&self); } struct RealImage{ file_name:String, } impl RealImage { fn load_from_disk(&self) { println!("Loading {}",self.file_name) } fn new(file_name:String)->RealImage { let i=RealImage { file_name:file_name.clone() }; i.load_from_disk(); i } } impl Image for RealImage { fn dispaly(&self) { println!("Displaying {}",self.file_name.as_str()) } } struct ProxyImage{ real_image: RealImage, file_name:String } impl ProxyImage { fn new(file_name:String)->ProxyImage { ProxyImage{ real_image:RealImage::new(file_name.clone()), file_name:file_name } } } impl Image for ProxyImage { fn dispaly(&self) { self.real_image.dispaly(); } } fn main() { let pi=ProxyImage::new("test_10mb.jpg".to_string()); pi.dispaly(); pi.dispaly(); }
rust仓库
https://github.com/onenewcode/design.git
本教程项目在bin文件夹下的proxy.rs文件中