23种设计模式----代理模式----结构型模式

代理模式

  • 1.什么是代理模式
  • 2.代理模式的角色
  • 3.例子
    • 3.1 背景
    • 3.2 例子结构
    • 3.3 抽象的共同的方法
    • 3.4 导购
    • 3.5 买家
    • 3.6 调用者
    • 3.7 结果
  • 4.总结

23种设计模式

1.什么是代理模式

代理这个词在生活中也很多。
最经典的一个就是在香港的警匪片中,反派老大被抓到警察局,然后反派老大说,我什么都不会交代,和我的律师说吧。
此时,律师就是反派老大在与警察交涉过程中的代理人。
还有一种情况就是反派老大管理的地盘太大,有些管理不过来,于是就设立了一个个的代理人。
不过,不管怎么样,当其他的反派老大拜访时,老大还是需要亲自招待的。
总结一下:代理就是一方面是补充本体不足,另一方面分担本体工作。
而有些事情只能由本体完成。

2.代理模式的角色

抽象的共同的操作
本体
代理人
调用者

3.例子

3.1 背景

相信每一个人都去过超市,或者商场等等。
所以呢,每一个人都会购物。
那么购物的步骤是怎么样的?
看到商品,先看看是不是自己需要的东西,然后看下商品的价格,与卖家砍砍价,最后成交。

大型的商场都有导购员,当你在看某件商品时,导购员就会介绍商品的有关信息。如果你接受导购员的服务,那么在这一时间内,导购员只会为你服务,不过,不管导购员如何诱惑,买不买还是买家的决定。

情况比较紧急或者商品不允许挑选(类似药品等特殊品)时,买家只需要付款就行。(还没见过砍价砍到药店的人才。。。。)

3.2 例子结构

23种设计模式----代理模式----结构型模式_第1张图片

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关键词修饰。

还有就是创建一个对象比较费时,使用代理可以先处理代理能够处理的操作,只有等到需要本体执行特定的操作时,才创建本体对象。
所以使用代理可以实现懒加载,懒创建等等,加快加载的速度。
23种设计模式

你可能感兴趣的:(java,设计模式)