学代理模式(静态代理,下面所属都指的是静态代理)的时候,敲着敲着代码,觉得怎么感觉像在写装饰器模式一样。所以在叙述代理模式的时候,我会用自己的理解去区分两种模式的区别。
在我上大学的城市,是没有苹果直营店的,但是有苹果的授权店,这个授权店概念就可以理解为代理。通过这个授权店我们同样能买到苹果的产品。
那么我怎么理解代理模式和装饰器模式的区别呢?首先看你的目的:你是需要在一个类上面增加功能(而且增加的功能还是动态的,可能不同的客户端会增加不一样的功能),那么这个时候你大致知道你要用装饰器模式了。或者你需要在使用类上面一个功能,同时加一点自己东西(也是增强功能),但是这个类是一个包级别的(比如苹果直营店在杭州,而我在河南),外部包无法直接取到这个类,那么你应该找一个代理了(河南的苹果代理),把需要的功能让代理类代理出去(去代理那里买苹果)。
我再说的直白点就是,你要访问国外网站,你需要翻墙才行,我可以把翻墙软件当作一个代理,通过它你就可以访问国外网站,与此同时这个翻墙软件(代理)也可以对你的访问做一些限制(某些网站,可能代理也不会让你访问)。而如果说你需要提高家里的无线网的网速,你可以自己掏钱升带宽,买一个更好的路由器,这个时候提升了网速,但是你对网速这个东西没有做任何改变。你只是提示了它的速度,速度再快它的本质也没改变。
所以说两种模式,在表面上给我我们都是增加功能的效果,但是实际上他们是为了解决不一样的问题,而产生的两种模式,你可以认为他们可以实现相同的目的(因为某些地方既可以有苹果直营店,也有授权店。在这里面你可以买到一样的东西,但是你能说他们是一样的吗),所以你不能说两种模式是一样的,可能在一些特定的情况下两种模式都可以用。
以上的话是对了解代理模式和装饰器模式小伙伴,说一说我的理解。如果你有更好的见解,欢迎留言。下面就来步入正题,看一下代理模式。
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
既然代理模式和装饰器模式很像,那么被代理的类和代理类肯定首先要共有一个接口。这里我们来写一个超市的接口
//超市
public interface Supermarket {
//零食
void snacks();
//家具
void furniture();
//服装
void clothing();
//日用品
void dailyNecessities();
}
现在超市的接口有了,那么我们来实现一个沃尔玛超市,注意这个WalMart是包级的,也就是在包外你是无法实例的,你可以理解为这个沃尔玛在美国,而我们在国内,为了逛个超市去美国开销太大,怎么办呢?中国也有沃尔玛的代理啊,去它们那里啊。
//沃尔玛
class WalMart implements Supermarket {
@Override
public void snacks() {
System.out.println("这里有沃尔玛零食");
}
@Override
public void furniture() {
System.out.println("这里有沃尔玛家具");
}
@Override
public void clothing() {
System.out.println("这里有沃尔玛服装");
}
@Override
public void dailyNecessities() {
System.out.println("这里有沃尔玛日用品");
}
}
既然我们无法访问美国的沃尔玛,我们只能访问代理,但是我们要知道这是在沃尔玛允许下,才会代理的,所有代理类我们要设置为public,此外这个代理目前只能代理零食。
//沃尔玛的代理
public class WalMartProxy implements Supermarket {
WalMart walMart = new WalMart();
@Override
public void snacks() {
walMart.snacks();
}
@Override
public void furniture() {
}
@Override
public void clothing() {
}
@Override
public void dailyNecessities() {
}
}
现在我们就想去逛沃尔玛的代理超市了,
public class Study {
public static void main(String[] args) {
Supermarket supermarket = new WalMartProxy();
supermarket.snacks();
}
}
在这里我们就通过代理买到沃尔玛的零食了,对于这种直接创建实例很困难的对象,我们可以通过代理来达到想要的效果,为什么说代理类可以控制被代理类呢?虽然被沃尔玛有权收回代理的授权,但是同样我也可以不要代理的权限,而且我还能买别人的零食,对于家具服装你不给我授权,我可以代理卖华联的家具服装,或者我自己进货去卖。
//沃尔玛的代理
public class WalMartProxy implements Supermarket {
WalMart walMart = new WalMart();
@Override
public void snacks() {
System.out.println("这里有其他的零食");
//如果不想让人买沃尔玛的零食了,或者零食卖完了,我们可以动态控制这个方法的调用
walMart.snacks();
}
@Override
public void furniture() {
System.out.println("虽然我没有代理沃尔玛家具,但是这里有我自己做家具");
}
@Override
public void clothing() {
}
@Override
public void dailyNecessities() {
}
}
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
说到这里对于代理类你有没有一个自己的理解呢?
欢迎进入小程序: