首页 > 代码库 > 代理模式

代理模式

0.前言

这个周五,设计模式老师来了一次突击检查,一个故作知识渊博的我倒下了……

1.本节我要说的是代理模式,作为一个对象结构型模式,我们有必要理解一下它的定义:给某一个对象【原对象】提供一个代理(对象),并由代理对象控制对原对象的引用。

2.我们来仔细品读这一句话,给某一个对象(即原对象)提供一个代理(对象),指的是我们有一个原对象A,我们需要为对象A提供一个代理服务,而做这个代理服务的对象即是代理对象,我们程其为代理对象B。“并且由代理对象控制对原对象的引用”。这里指得是代理对象中拥有一个原对象.并且维持这样一个原对象的引用。

3.好了,我们开始一个实例分析(我拿出我们设计模式课老师在上周五的考试题)

张师傅以前喜欢炒股,因为股票需要自己选,而自己对股市又不熟,所以总是亏钱。后听人介绍说可以买基金,因为基金是由专门对股市或其他资本市场很有研究的人来操作的。张师傅只需要把钱交给基金公司就可以了,由基金公司来向股市或其他市场投资,张师傅也可以随时将投入的资金从基金公司赎回。现假设该基金公司共购买两只股票和一种国债,并投资了某房地产企业。当张师傅赎回基金时,基金公司需要将股票、国债、房地产全部卖掉。

1) 试问根据该描述应该采用哪一种设计模式,并给出其类图。(30分)

2)试根据题意设计满足题意要求的类和客户端代码。(70分)

4.仔细通读一下这个题目,我们发现这里有一个类MrZhang,作为一个买股票的普通股民。他想买股票,但是比较好的一个方式是让代理公司代买股票,所以这里的代理类就是代理公司Company。这个公司负责买股票,债券两种,我们将其分别作为原对象Share(股票),Bond(债券),他们均继承自“Investment”(投资)类。所以有:

(1)MrZhang:代表普通股民类

(2)Company:代理公司类

(3)Investment:抽象投资类

(4)Share:股票类

(5)Bond:债券类

根据题目,我们可以得到上面的所有类,但是是不是还差了点儿什么?我们只是将真实主题即Share,Bond类抽象成了Investment类,但是不是说抽象抽象再抽象嘛?难道只有一个抽象?当然不止,我们可以看到,在上面的分析中,MrZhang想从代理公司买股票,但是现实生活中或许这种代理公司并不是只有公司A啊,或许还有B呢,或者C?假设在后期想更换系统的 时候,难道我们都要把他们一个一个都补上去?当然不是,所以这里应该有一种更加好的办法,那就是使用抽象,将代理对象和原对象一起抽象,这样就得到了一个抽象类Subject,即:

(6)Subject:抽象主题类

5.分析完上面的题目,接着我们该怎么做呢?写代码!!代码如下:

package liu.shen;


/**
 * 抽象主题  Subject
 * @author Object
 *
 */
public abstract  class Subject {
	abstract void buy(MrZhang mrZhang);//购买方法---->但是买谁呢?需要一个参数
	abstract void undo(MrZhang mrZhang);//赎回投资	
}

package liu.shen;


/**
 *代理公司类,负责买证券或者股票 
 * @author Object
 *
 */
public class CompanyA extends Subject{
		

	Investment investment1 = new Share();
	Investment investment2= new Share();
	Investment investment3 = new Bond();	
	
	
	public void display(){
		System.out.println("我是代理公司A!");
	}
	
	void buy(MrZhang mrZhang) {		
		investment1.buy(mrZhang);
		investment2.buy(mrZhang);
		investment3.buy(mrZhang);
	}

	//撤销
	@Override
	void undo(MrZhang mrZhang) {
		// TODO Auto-generated method stub
		investment1.undo(mrZhang);
		investment2.undo(mrZhang);
		investment3.undo(mrZhang);
	}
}

package liu.shen;

/**
 * 代理公司B:继承自Subject类
 * @author Object
 *
 */
public class CompanyB extends Subject{
	public void display(){
		System.out.println("我是代理公司B!");
	}
	
	Investment investment1 = new Share();//这个地方也可以使用xml文件
	Investment investment2= new Share();
	Investment investment3 = new Bond();	
	

	
	void buy(MrZhang mrZhang) {		
		investment1.buy(mrZhang);
		investment2.buy(mrZhang);
		investment3.buy(mrZhang);
	}

	//撤销
	@Override
	void undo(MrZhang mrZhang) {
		// TODO Auto-generated method stub
		investment1.undo(mrZhang);
		investment2.undo(mrZhang);
		investment3.undo(mrZhang);
	}
}

package liu.shen;


/***
 * 投资类抽象类,作为一个真实主题
 * @author Object
 *
 */
public abstract class Investment extends Subject {
	
	@Override
	void buy(MrZhang mrZhang) {
		// TODO Auto-generated method stub
		
	}
	
	void undo(MrZhang mrZhang){
		
	}

}

package liu.shen;


/**
 * 股票(一种炒股方式),继承自Investment()--投资类
 * @author Object
 *
 */
public class Share extends Investment{


	@Override
	void buy(MrZhang mrZhang) {
		if(mrZhang.money > 1000){
			System.out.println (mrZhang.name+"以1000元"+"买了一份股票!");
			mrZhang.money -=1000;
			System.out.println(mrZhang.name+"赎回股票后的金额为:"+mrZhang.money);
		}
				
	}

	@Override
	void undo(MrZhang mrZhang) {
		// TODO Auto-generated method stub		
		System.out.println(mrZhang.name+"赎回一份股票!");
		mrZhang.money +=1000;		
		System.out.println(mrZhang.name+"赎回股票后的金额为:"+mrZhang.money);
	}
	
	
}

package liu.shen;


/**
 * 债券,继承自Investment()--投资类
 * @author Object
 *
 */
public class Bond extends Investment{

	@Override
	void buy(MrZhang mrZhang) {
		if(mrZhang.money>2000){
			System.out.println(mrZhang.name+"以1000元买了一份债券!");
			mrZhang.money -=2000;
			System.out.println(mrZhang.name+"购买债券后的金额为:"+mrZhang.money);
		}		
	}
	

	@Override
	void undo(MrZhang mrZhang) {
		// TODO Auto-generated method stub
		System.out.println(mrZhang.name+"准备赎回一份债券!");
		mrZhang.money += 2000;
		System.out.println(mrZhang.name+"赎回债券后的金额为:"+mrZhang.money);
	}

}

package liu.shen;


/**
 * MrZhang 代表真实主题角色,继承自抽象主题Subject
 * @author Object
 *
 */
public class MrZhang {
	int money;//金钱
	String name;//姓名	
	
	public  void buy(){			
					
	}
	
	public void undo(){
		
	}
	
	public MrZhang(String name ,int money){
		this.name = name;
		this.money = money;
	}
	
	public static void main(String []args){		
		MrZhang mrZhang = new MrZhang("张三",20000);
		
		Subject subject =  new CompanyA();	
		subject.buy(mrZhang);
		System.out.println("------------------");
		subject.undo(mrZhang);
	}	
}

6.运行结果

技术分享


7.模式总

(1)对于代理模式来说,最重要的地方就是我们需要在代理类(即CompanyA或者CompanyB)中维持一个原对象的引用,相应的本文中的体现就是在CompanyA中的如下语句:

Investment share1 = new Share();
Investment share2= new Share();
Investment bond3 = new Bond();	
因为只有在代理对象中维持了一个或几个真实对象才能使用真实主题的一些方法,比如说这里的buy(),undo()等。

(2)在上面的代码中,我们有两处地方是这么写的:

Investment share1 = new Share();
还有就是

Subject subject =  new CompanyA();	

但是在实际生活中,这么写是不好的,我们需要引用配置文件读取我们所需要的内容,所以我准备今天晚上用一门专门的博客来介绍java中读取xml文件的细节内容,详情请在博客主页中搜索啦。


8.虽然啰里啰嗦写了一大堆,但是我真的表示周五那天下午的大作业没有写好。事实也证明了,不要抱着侥幸的心态,我就是觉得我已经大致掌握了百分之九十的设计模式的基础题目了,就没有再深入的了解代理模式,命令模式……但结果是你真的不知道老师会出什么考题,在你知道是什么考题之前,最好把所有的知识点都给复习一遍,这是最好的,也是最安全的办法。


代理模式