理模式
1、不使用代理模式
举例说明:小明喜欢一个女生(小红),因为小红不认识小明,所以小明通过叫小华代替他送礼物给小红
可以得出的结果图:
被追求者:
/** * @author Shier * CreateTime 2023/4/17 22:06 * 目标对象:被追求者小红 */ public class ObjectGirl { private String girlName; public String getGirlName() { return girlName; } public void setGirlName(String girlName) { this.girlName = girlName; } }
追求者:
/** * @author Shier * CreateTime 2023/4/17 22:04 * 追求者 */ public class Pursuit { private ObjectGirl girl; public Pursuit(ObjectGirl girl) { this.girl = girl; } public void giveFlowers() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的花。"); } public void giveChocolate() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的巧克力。"); } public void giveDolls() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的洋娃娃。"); } }
测试类:
/** * @author Shier * CreateTime 2023/4/17 22:09 */ public class ProxyTest { public static void main(String[] args) { ObjectGirl xiaohong = new ObjectGirl(); xiaohong.setGirlName("小红"); Pursuit xiaoming = new Pursuit(objectGirl); xiaoming.giveDolls(); xiaoming.giveFlowers(); xiaoming.giveChocolate(); } }
但是你会发现,如果是这样实现的哇,就相当于小明和小红之间是认识的,但是我们的例子是说小明和小红之间不认识,所以说这样子是不能的,所以说我要通过小华这个“中间人” 😂
2、第一次修改-只有代理模式
修改之后的UML图如下:
代理类:
/** * @author Shier * CreateTime 2023/4/17 22:04 * 代理类 */ public class Proxy { private ObjectGirl girl; public Proxy(ObjectGirl girl) { this.girl = girl; } public void giveFlowers() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的花。"); } public void giveChocolate() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的巧克力。"); } public void giveDolls() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的洋娃娃。"); } }
客户端:
/** * @author Shier * CreateTime 2023/4/17 22:09 */ public class ProxyTest { public static void main(String[] args) { ObjectGirl xiaohong = new ObjectGirl(); xiaohong.setGirlName("小红"); Pursuit xiaohua = new Pursuit(xiaohong); xiaohua.giveDolls(); xiaohua.giveFlowers(); xiaohua.giveChocolate(); } }
观察发现,只有代理人了,就相当于是小华直接向小红进行表白了,就把小明忽略掉了
3、 符合实际的代码
接口:
/** * @author Shier * CreateTime 2023/4/17 22:21 */ public interface GiveGift { void giveDolls(); void giveFlowers(); void giveChocolate(); }
代理:
/** * @author Shier * CreateTime 2023/4/17 22:04 * 代理类 */ public class Proxy implements GiveGift { private Pursuit pursuit; //认识追求者 public Proxy(ObjectGirl girl) { // 也认识被追求者 this.pursuit = new Pursuit(girl); // 代理初始化,实际就是追求者初始化过程 } public void giveFlowers() { // 代理者向被追求者松礼物 this.pursuit.giveFlowers(); } public void giveChocolate() { this.pursuit.giveChocolate(); } public void giveDolls() { this.pursuit.giveDolls(); } }
追求者:
/** * @author Shier * CreateTime 2023/4/17 22:04 * 追求者 */ public class Pursuit implements GiveGift{ private ObjectGirl girl; public Pursuit(ObjectGirl girl) { this.girl = girl; } public void giveFlowers() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的花。"); } public void giveChocolate() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的巧克力。"); } public void giveDolls() { System.out.println(this.girl.getGirlName() + ",你好!,小明叫我送给你的洋娃娃。"); } }
被追求者同上。
最后的结果都是一样的:
4、代理模式
代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在代理模式中,一个类代表另一个类或一些类的功能。这种类型的设计模式属于结构型模式。代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
在代理模式中,通常会涉及到三个角色:抽象主题角色、真实主题角色和代理主题角色。
抽象主题角色声明了真实主题角色和代理主题角色的公共方法
真实主题角色实现了抽象主题角色定义的接口,代表着真实的业务实现
代理主题角色持有真实主题角色的引用,可以访问真实主题角色,同时还可以在真实主题角色基础上添加一些附加的操作
代理模式有两种不同的实现方式:静态代理和动态代理。在静态代理中,代理类在编译期间就已经确定,并且只能代理特定的接口或者类;在动态代理中,代理类是在运行时动态生成的,可以代理任意接口或者类。
代理模式的优点:
职责清晰
高扩展性
智能化
代理模式可以控制对对象的访问,从而实现一些安全性或者监控的功能。
在使用代理模式时,需要注意的是,代理类和被代理类通常应该共同实现一个接口或者继承自同一个父类,并且需要仔细考虑代理类的生命周期和线程安全性等问题。
4.1 代理模式结构图
ISubject类,定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
ISubject类:
/** * @author Shier * CreateTime 2023/4/17 22:35 * 代理类和真实类都要实现的接口 */ public interface ISubject { void request(); }
RealSubject类:
/** * @author Shier * CreateTime 2023/4/17 22:36 * 真实的实体类 */ public class RealSubject implements ISubject { @Override public void request() { System.out.println("RealSubject do something"); } }
代理类:
/** * @author Shier * CreateTime 2023/4/17 22:36 * 代理类:代理真实类完成一些列的操作 */ public class Proxy implements ISubject { private RealSubject rs; // 拥有真实类的属性 public Proxy() { this.rs = new RealSubject(); // 代理初始化,也就是真实类的初始化过程 } // 代理类要做的事情 public void request() { this.rs.request(); } }
客户端:
/** * @author Shier * CreateTime 2023/4/17 22:39 */ public class Test { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.request(); // 通过代理发送给RealSubject类 // RealSubject do something } }
5、 代理模式应用
远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实
虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象
安全代理,用来控制真实对象访问时的权限
智能指引,是指当调用真实的对象时,代理处理另外一些事
ng[] args) {
Proxy proxy = new Proxy();
proxy.request(); // 通过代理发送给RealSubject类 // RealSubject do something
}
}
## 5、 代理模式应用 1. 远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实 2. 虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象 3. 安全代理,用来控制真实对象访问时的权限 4. 智能指引,是指当调用真实的对象时,代理处理另外一些事