携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第二十天,点击查看活动详情
重学设计模式之代理模式
定义 代理模式(Proxy Parttern) 为一个对象提供一个替身, 来控制这个对象的访问,即通过代理对象来访问目标对象, 这样做的话好处是可以在目标对象实现的基础上,进行额外的功能的扩展。
代理模式包含如下角色: 抽象主题角色(Subject):抽象主题类的主要职责是声明真实主题与代理的共同接口方法,该类可以是接口也可以是抽象类;
真实主题角色(RealSubject):该类也被称为被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象;
代理主题角色(Proxy):也被称为代理类,其内部持有 RealSubject 的引用,因此具备完全的对 RealSubject的代理权。 客户端调用代理对象的方法,同时也调用被代理对象的方法,但是会在代理对 象前后增加一些处理代码。
优点:
-
代理模式能将代理对象与真实被调用目标对象分离。
-
在一定程度上降低了系统的耦合性,扩展性好。
-
可以起到保护目标对象的作用。
-
可以增强目标对象的功能。 缺点: 代理模式会造成系统设计中类的数量增加。
在客户端和目标对象中增加一个代理对象,会导致请求处理速度变慢。
增加了系统的复杂度。
例子: 例如卖票功能 抽象主题角色:
public interface TicketTest {
void sellTicket();
}
真实主题角色(电影院)
public class Cinema implements TicketTest {
@Override
public void sellTicket() {
System.out.println("电影院卖电影票");
}
}
代理主题角色(线上售卖电影票平台)
public class OnlineSeller implements TicketTest {
private Cinema cinema;
public OnlineSeller(Cinema cinema) {
this.cinema = cinema;
}
@Override
public void sellTicket() {
sellBefore();
cinema.sellTicket();
sellAfter();
}
//增强内容(卖票之前的自定义操作)
private void sellBefore() {
System.out.println("线后上平台在卖票之前开始打广告");
}
//增强内容(卖票之的自定义操作)
private void sellAfter() {
System.out.println("线上平台在卖票之后统计售票情况");
}
}
测试
public static void main(String[] args) {
OnlineSeller onlineSeller=new OnlineSeller(new Cinema());
onlineSeller.sellTicket();
//输出类容:
线上平台在卖票之前开始打广告
电影院卖电影票
线上平台在卖票之后统计售票情况
}
静态代理和动态代理的区别:
- 静态代理只能通过手动完成代理操作,如果被代理类增加了新的方法,代理类需要同步增加, 违背开闭原则。
- 动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开闭原则。 3.若动态代理要对目标类的增强逻辑进行扩展,结合策略模式,只需要新增策略类便可完成,无须修改代理类的代码。 例如,上面的例子静态类,线上售卖电影票系统只能卖电影票,不能卖其他票类,如果要卖其他票类,那么需要增加相应的代理类
动态代理可以解决上述问题: 例子: 代理主题角色(综合卖票平台)
public class Seller implements InvocationHandler {
private TicketTest ticketTest;
//反射获取
public TicketTest getInstance(TicketTest ticketTest){
this.ticketTest = ticketTest;
Class<?> clazz = ticketTest.getClass();
return (TicketTest) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(this.ticketTest,args);
after();
return result;
}
//增强内容(卖票之后的自定义操作)
private void after() {
System.out.println("卖票结束,统计数据");
}
//增强内容(卖票之前的自定义操作)
private void before() {
System.out.println("我是代理商,开始帮忙卖票");
}
}
真实主题角色(飞机场)
public class AirPlane implements TicketTest {
@Override
public void sellTicket() {
System.out.println("飞机场卖飞机票票");
}
}
测试动态代理
public static void main(String[] args) {
Seller seller=new Seller();
TicketTest ticketTest= seller.getInstance(new Cinema());
ticketTest.sellTicket();
TicketTest ticketTest2= seller.getInstance(new AirPlane());
ticketTest2.sellTicket();
//输出类容:
我是代理商,开始帮忙卖票
电影院卖电影票
卖票结束,统计数据
我是代理商,开始帮忙卖票
飞机场卖飞机票票
卖票结束,统计数据
}