概念就不写了,直接写三种代理模式的实现方式:
静态代理
在程序运行前,代理类。class文件就已经生成了。是比较固定的实现,相对于动态生成代理来说这就是所谓的静态代理吧。我按自己的理解说的。
我们都知道,被静态代理的对象必须要实现一个接口,举个栗子。有些公司太严格,不许员工访问一些娱乐网站。怎么实现?当然是加权限,加这些娱乐网站的黑名单。就比如我在鹅厂,谁敢访问个支付宝试试。然后鹅厂就要给zhifubao加个网络连接的黑名单。我们简单看看用静态代理怎么实现。
首先,我们要定义一个上网的接口,让上网的人都访问这个接口:
public interface Internet {
void connectTo(String hostName) throws Exception;
}
然后我们有个真实上网的对象去实现上网接口里规定的连接功能,当然就是被管理的对象咯。
public class RealInternet implements Internet {
@Override
public void connectTo(String hostName) throws Exception {
System.out.println("小姐姐要访问 :" + hostName);
}
}
那么被代理对象有了,我们怎么去实现对上网的管控呢?
首先,代理对象也要实现上网接口,其次,我们要让每个要上网的同学都必须把对象给我,当然此对象非彼对象哈。我要好好看看你到底有没有访问zhifubao,如果有不好意思,打屁股。
我们这样实现:
public class ProxyInternet implements Internet {
/**
* 不好意思,哥一夫当关
*/
private Internet internet;
/**
* 来了啊,小姐姐
*
* @param internet 小姐姐本尊
*/
public ProxyInternet(Internet internet) {
this.internet = internet;
}
/**
* 黑名单
*/
private static List<String> bannedSites = new ArrayList<>();
static {
bannedSites.add("www.alibaba.com");
bannedSites.add("www.alimama.com");
bannedSites.add("www.alijiujiu.com");
bannedSites.add("www.dingding.com");
bannedSites.add("www.zhifubao.com");
}
/**
* 这里是你做错事的惩罚
*
* @param hostName 小姐姐访问的网站
*/
@Override
public void connectTo(String hostName) throws Exception {
if (bannedSites.contains(hostName)) {
throw new Exception("访问" + hostName + "被我打了屁股!");
}
//绿色通道
internet.connectTo(hostName);
}
}
然后小伙伴不听劝告悄悄上网了,还访问了阿里mama
public class Client {
public static void main(String[] args) {
Internet internet = new ProxyInternet(new RealInternet());
try {
internet.connectTo("www.alimama.com");
} catch (Exception e) {
System.out.println("然后,小姐姐"+e.getMessage());
}
}
}
然后事情的结局是这样的:
当然也有听话的小伙伴
我们还可以用工厂模式来完全隐藏真实上网对象的逻辑实现:
public class Factory {
public static Object newInstance(String name) {
return new ProxyInternet(new RealInternet(name));
}
}
public class RealInternet implements Internet {
private String name;
public RealInternet(String name) {
this.name = name;
}
@Override
public void connectTo(String hostName) throws Exception {
System.out.println("小姐姐" +name+"要访问 :" + hostName);
}
}
然后
public class Client {
public static void main(String[] args) {
Internet internet = (Internet) Factory.newInstance("小月亮");
try {
internet.connectTo("www.qq.com");
System.out.println("小姐姐很乖,很听话!");
} catch (Exception e) {
System.out.println("然后,小姐姐"+e.getMessage());
}
}
}
我们看到Client里面没有任何 RealInternet 的信息,然后打印:
小姐姐小月亮要访问 :www.qq.com
小姐姐很乖,很听话!
总结
下面我们总结下优缺点:
优点
对被代理对象不做任何修改,甚至都看不到被代理对象的实现。只需要被代理对象交给代理对象代理就可以。我们称之为解耦。
缺点
代理类和被代理类都需要实现同一个接口,Override相同的方法,这样无形中增加了代码的冗余度
我们知道,接口中的方法实现类是必须要实现的,所以一旦我们增加或者修改接口中的方法的时候,实现类中的方法也要跟着修改。这也就增加了维护的难度
例子中ProxyInternet只能服务于Internet类型的对象。如果我们增加一种别的类型的对象,它就没办法代理了。要实现代理就必须对每一种对象都生成代理类才可以。所以如果需要代理的种类很多很多,静态代理就无法胜任了。