23种设计模式----代理模式----结构型模式
原创
©著作权归作者所有:来自51CTO博客作者qq5963a5404b339的原创作品,请联系作者获取转载授权,否则将追究法律责任
代理模式
23种设计模式
1.什么是代理模式
代理这个词在生活中也很多。
最经典的一个就是在香港的警匪片中,反派老大被抓到警察局,然后反派老大说,我什么都不会交代,和我的律师说吧。
此时,律师就是反派老大在与警察交涉过程中的代理人。
还有一种情况就是反派老大管理的地盘太大,有些管理不过来,于是就设立了一个个的代理人。
不过,不管怎么样,当其他的反派老大拜访时,老大还是需要亲自招待的。
总结一下:代理就是一方面是补充本体不足,另一方面分担本体工作。
而有些事情只能由本体完成。
2.代理模式的角色
抽象的共同的操作
本体
代理人
调用者
3.例子
3.1 背景
相信每一个人都去过超市,或者商场等等。
所以呢,每一个人都会购物。
那么购物的步骤是怎么样的?
看到商品,先看看是不是自己需要的东西,然后看下商品的价格,与卖家砍砍价,最后成交。
大型的商场都有导购员,当你在看某件商品时,导购员就会介绍商品的有关信息。如果你接受导购员的服务,那么在这一时间内,导购员只会为你服务,不过,不管导购员如何诱惑,买不买还是买家的决定。
情况比较紧急或者商品不允许挑选(类似药品等特殊品)时,买家只需要付款就行。(还没见过砍价砍到药店的人才。。。。)
3.2 例子结构
3.3 抽象的共同的方法
package proxyable;
/**
*
* 到超时买东西必备的技能
* 1.东西的名称
* 2.买家的名称
* 3.问价格
* 4.砍价
* 5.成交
*
*
*/
public interface BuySomething {
String getThingName();
String getBuyerName();
void setBuyerName(String buyerName);
int getThingPrice(String thingName);
int bargainirg(String thingName,String buyerName);
void deal(String thingName,String buyerName);
}
3.4 导购
package proxy;
import proxyable.BuySomething;
/**
*
* 从某种程度上来说,导购就是买家的一个代理人
*
*/
public class Guide implements BuySomething{
private String buyerName;
private BuySomething buySomething;
public Guide(String buyName) {
this.buyerName = buyName;
}
@Override
public String getThingName() {
System.out.println("导购熟悉超市环境,获取商品名称的速度比买家快");
return "thingName";
}
@Override
public void setBuyerName(String buyerName) {
System.out.println("导购需要明确的知道,自己服务的买家是谁"+buyerName);
if(buySomething == null){
try{
buySomething = create(buyerName);
} catch (Exception e){
e.printStackTrace();
}
}
buySomething.setBuyerName(buyerName);
this.buyerName = buyerName;
}
@Override
public int getThingPrice(String thingName) {
System.out.println("导购询问价格一般都比较贵");
return 100;
}
@Override
public int bargainirg(String thingName, String buyerName) {
System.out.println("导购砍价几乎是象征性的砍价");
return 0;
}
/**
* 被代理者无法替代的工作
*/
@Override
public void deal(String thingName, String buyerName) {
System.out.println("不管导购多么的努力,决定权还是在买家身上");
if(buySomething == null){
try {
buySomething = create(buyerName);
} catch (Exception e){
e.printStackTrace();
}
}
buySomething.deal(thingName, buyerName);
}
private synchronized BuySomething create(String buyerName) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
return (BuySomething) Class.forName("real."+buyerName).newInstance();
}
@Override
public String getBuyerName() {
return this.buyerName;
}
}
3.5 买家
package real;
import proxyable.BuySomething;
public class Buyer implements BuySomething{
private String name;
@Override
public String getThingName() {
System.out.println("买家不熟悉超市的环境,所以获取商品的名称比较慢");
return "thingName";
}
@Override
public int getThingPrice(String thingName) {
System.out.println("买家询问价格同样贵");
return 100;
}
@Override
public int bargainirg(String thingName, String buyerName) {
System.out.println("买家砍价比较狠");
return 10;
}
@Override
public void deal(String thingName, String buyerName) {
System.out.println("买家经过长时间的考虑,最终决定买下来");
}
@Override
public void setBuyerName(String buyerName) {
System.out.println("现在的操作人"+buyerName);
this.name = buyerName;
}
@Override
public String getBuyerName() {
return this.name;
}
}
3.6 调用者
package client;
import proxy.Guide;
import proxyable.BuySomething;
public class Main {
public static void main(String[] args) {
System.out.println("逛超市吧");
System.out.println("导购全权购买");
BuySomething buySomething = new Guide("Guide");
System.out.println(buySomething.getThingName());
System.out.println(buySomething.getBuyerName());
System.out.println(buySomething.getThingPrice(buySomething.getThingName()));
System.out.println(buySomething.bargainirg(buySomething.getThingName(),
buySomething.getBuyerName()));
buySomething.deal(buySomething.getThingName(), "Buyer");
System.out.println("导购帮助选购,本人砍价,购买");
System.out.println(buySomething.getThingName());
System.out.println(buySomething.getBuyerName());
System.out.println(buySomething.getThingPrice(buySomething.getThingName()));
buySomething.setBuyerName("Buyer");
System.out.println(buySomething.bargainirg(buySomething.getThingName(),
buySomething.getBuyerName()));
buySomething.deal(buySomething.getThingName(), buySomething.getBuyerName());
System.out.println("本人出马");
buySomething.setBuyerName("Buyer");
System.out.println(buySomething.getThingName());
System.out.println(buySomething.getBuyerName());
System.out.println(buySomething.getThingPrice(buySomething.getThingName()));
System.out.println(buySomething.bargainirg(buySomething.getThingName(),
buySomething.getBuyerName()));
buySomething.deal(buySomething.getThingName(), buySomething.getBuyerName());
}
}
3.7 结果
逛超市吧
导购全权购买
导购熟悉超市环境,获取商品名称的速度比买家快
thingName
Guide
导购熟悉超市环境,获取商品名称的速度比买家快
导购询问价格一般都比较贵
100
导购熟悉超市环境,获取商品名称的速度比买家快
导购砍价几乎是象征性的砍价
0
导购熟悉超市环境,获取商品名称的速度比买家快
不管导购多么的努力,决定权还是在买家身上
买家经过长时间的考虑,最终决定买下来
导购帮助选购,本人砍价,购买
导购熟悉超市环境,获取商品名称的速度比买家快
thingName
Guide
导购熟悉超市环境,获取商品名称的速度比买家快
导购询问价格一般都比较贵
100
导购需要明确的知道,自己服务的买家是谁Buyer
现在的操作人Buyer
导购熟悉超市环境,获取商品名称的速度比买家快
导购砍价几乎是象征性的砍价
0
导购熟悉超市环境,获取商品名称的速度比买家快
不管导购多么的努力,决定权还是在买家身上
买家经过长时间的考虑,最终决定买下来
本人出马
导购需要明确的知道,自己服务的买家是谁Buyer
现在的操作人Buyer
导购熟悉超市环境,获取商品名称的速度比买家快
thingName
Buyer
导购熟悉超市环境,获取商品名称的速度比买家快
导购询问价格一般都比较贵
100
导购熟悉超市环境,获取商品名称的速度比买家快
导购砍价几乎是象征性的砍价
0
导购熟悉超市环境,获取商品名称的速度比买家快
不管导购多么的努力,决定权还是在买家身上
买家经过长时间的考虑,最终决定买下来
4.总结
大概有一下几点:
首先对于一些方法,代理相当于是透明的,比如上述例子中的setBuyerName方法和deal方法,不管调用的是代理的方法还是本体的方法,最后都是调用本体的方法。所以代理在这两个方法中就相当于是透明的。
至于透明的实现方式,是通过委托来实现的。
可以很清楚的知道,每一个代理都会持有一个本体的对象,当遇到代理无法完成的操作时,代理就会创建本体的对象,然后把操作交给本体完成。
当代理和反射之间的关系非常的复杂或者调用非常的频繁时,可以使用反射的方式。比如在例子中,新增一个本体,只需要重新写一个本体的类就行,调用的时候设置名字就是类名就ok。可以无限的复用代理类。
同样的由于代理类持有的是接口,而接口代理与本体都需要实现方法,所以,新增一个代理可以使用原来的本体。
这样就做到本体与代理相互补充,无限扩充。
考虑到多线程或者多个代理需要创建同一个本体的情况,代理创建本体的方法应该用synchronized关键词修饰。
还有就是创建一个对象比较费时,使用代理可以先处理代理能够处理的操作,只有等到需要本体执行特定的操作时,才创建本体对象。
所以使用代理可以实现懒加载,懒创建等等,加快加载的速度。