论坛首页 编程语言技术论坛

设计模式(六)——抽象工厂模式

浏览 5729 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-07-09   最后修改:2012-11-14

设计模式(六)——抽象工厂模式

 

感冒了几天,没写。今天继续,上次写到工厂方法模式了,总的来说,工厂方法模式还是挺简单的,这次讲的抽象工厂模式,听名字也知道应该是与工厂模式是一脉相承的,顾名思义就是将工厂模式抽象化了,是的,木有错,就是这样,实质上就是在具体产品和具体实现工厂与各自接口中间再加入了一个抽象类,这样做有什么好处?废话,没好处我闲的那什么疼要多加一层?现在不说,写完一看就知道,然后这里引入两个专业概念:产品等级,产品族。其实很好理解,先记着,用到的时候讲。

我们接着上一讲的例子,仍然是老板要造汽车,现在的情况是,老板有间汽车工厂,可以造奥迪和奔驰车,但是老板想,奥迪和奔驰有各种不同型号的车嘛,是的,那。。。我也不是卖车的,也没买过奥迪和奔驰,我也不知道有哪些型号,呵呵,嗯,早知道我应该举个造电脑的例子我可能熟悉点,不管了,我就假设奥迪的车都分为两种,一种普通的车,一种特殊型号的车,特殊用途的,具体什么特殊用途你自己想象。同样奔驰车也大体归为这两大类。

那我们首先还是定义一个所有车的接口,不过这次我们加个型号:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:Car <br/>
 * Function: 定义一个汽车的公共接口. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-4 下午2:04:52 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public interface Car {

	/**
	 * run:车都可以跑. <br/>
	 * @author gongyong
	 * @since JDK 1.6
	 */
	public void run();

	/**
	 * style:车都有个型号. <br/>
	 * @author gongyong
	 * @since JDK 1.6
	 */
	public void style();

}

 然后,我们定义一个抽象的汽车类来实现这个公共的汽车接口,这里有个有意思的地方,就是面试的时候经常会被问到的一个问题,面试官问你,抽象类如果实现了某个接口是不是一定要实现该接口的所有方法?你说呢,呵呵,往下看:

抽象的奥迪汽车类:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:   AudiCar <br/>
 * Function:    奥迪车的抽象类. <br/>
 * Reason:      TODO ADD REASON(可选). <br/>
 * date:        2012-7-6 下午3:02:14 <br/>
 *
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 */
public abstract class AudiCar implements Car{
	/**
	 *奥迪可以跑.
	 * @see com.gy.designpattern.factorymethod.Car#run()
	 */
	@Override
	public void run(){
		System.out.println("奥迪在跑!");
	}
}

 抽象的奔驰车类:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:BenzCar <br/>
 * Function: 奔驰汽车抽象模型 <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-4 下午2:09:00 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public abstract class BenzCar implements Car{

	/**
	 * 奔驰可以跑.
	 * @see com.gy.designpattern.factorymethod.Car#run()
	 */
	@Override
	public void run(){

		System.out.println("奔驰在跑!");
	}
}
 

先把所有的汽车的具体实现都写完再写工厂类吧,下面是具体的汽车类:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:NormalAudiCar <br/>
 * Function: 这是正常型号的奥迪车的具体类. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:39:25 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class NormalAudiCar extends AudiCar{

	/**
	 * 定义汽车的型号.
	 * @see com.gy.designpattern.abstractfactory.Car#style()
	 */
	@Override
	public void style(){
		System.out.println("这是正常型号的奥迪车");
	}
}

 package com.gy.designpattern.abstractfactory;

/**
 * ClassName:NormalBenzCar <br/>
 * Function: 普通型号的奔驰车. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:42:50 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class NormalBenzCar extends BenzCar{

	/**
	 * 定义汽车的型号
	 * @see com.gy.designpattern.abstractfactory.Car#style()
	 */
	@Override
	public void style(){
		System.out.println("这是正常型号的奔驰车");
	}
}
 

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:SpecialAudiCar <br/>
 * Function: 特殊型号的奥迪车. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:41:22 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class SpecialAudiCar extends AudiCar{

	/**
	 * 特殊型号的奥迪车.
	 * @see com.gy.designpattern.abstractfactory.Car#style()
	 */
	@Override
	public void style(){
		System.out.println("这是特殊型号的奥迪车");

	}

}

 

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:SpecialAudiCar <br/>
 * Function: 特殊型号的奔驰车. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:41:22 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class SpecialBenzCar extends BenzCar{

	/**
	 * 特殊型号的奔驰车.
	 * @see com.gy.designpattern.abstractfactory.Car#style()
	 */
	@Override
	public void style(){

		System.out.println("这是特殊型号的奔驰车");

	}

}

 好了,讲到这里,所有的具体的汽车类都实现了,还记得前面讲到的两个专业术语吧,产品等级和产品族,不拽文了,前面的两个抽象的汽车类就叫产品等级,继承了这两个抽象类的具体的汽车类就叫产品族,that's it,就这样,不是我非要拽这俩词,是很多写的很专业的设计模式的书里老提这俩词,显得很高端,其实,你懂的。。。go on

然后我们来看工厂类:

我们也先定义下工厂的接口,注意了,这里和工厂方法模式不一样了,工厂方法模式里是直接写了一个具体的工厂类,而我们这里先写个接口,然后再写一个抽象的工厂类实现该接口,如下:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:CarFactory <br/>
 * Function: 汽车工厂接口. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:06:15 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public interface CarFactory {

	/**
	 * createAudiCar:创建奥迪车的工厂. <br/>
	 * @author gongyong
	 * @return
	 * @since JDK 1.6
	 */
	public Car createAudiCar();

	/**
	 * createBenzCar:创建奔驰车的工厂. <br/>
	 * @author gongyong
	 * @return
	 * @since JDK 1.6
	 */
	public Car createBenzCar();

}
 

抽象的工厂类:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:AbstractCarFactory <br/>
 * Function: 抽象的工厂类. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:08:44 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public abstract class AbstractCarFactory implements CarFactory{

	/**
	 * createCar:根据枚举类型创建汽车. <br/>
	 * @author gongyong
	 * @param carEnum
	 * @return
	 * @since JDK 1.6
	 */
	protected Car createCar(CarEnum carEnum){
		Car car = null;

		if(!(carEnum.getValue().equals(""))){
			try{
				//产生实例
				car=(Car)Class.forName(carEnum.getValue()).newInstance();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return car;

	}
}

注意,这里我用到枚举这个东东,其实完全可以不用,我只是最近看到了就想试试而已,学以致用嘛,稍后贴出这个枚举的的代码,这里不跑题,然后我们写两个具体的工厂类,一个是专门生产普通型号的车的,一个是生产特殊型号的:
package com.gy.designpattern.abstractfactory;
/**
 * ClassName:AudiCarFactory <br/>
 * Function: 生产普通型号的汽车的工厂. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:23:37 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class NormalCarFactory extends AbstractCarFactory{

	/**
	 * 创建正常型号奥迪车.
	 * @see com.gy.designpattern.abstractfactory.CarFactory#createAudiCar()
	 */
	@Override
	public Car createAudiCar(){

		return super.createCar(CarEnum.AudiNormalCar);

	}

	/**
	 * 创建正常型号奔驰车.
	 * @see com.gy.designpattern.abstractfactory.CarFactory#createBenzCar()
	 */
	@Override
	public Car createBenzCar(){

		return super.createCar(CarEnum.BenzNormalCar);

	}
}
 
 

 

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:SpecialCarFactory <br/>
 * Function: 制造特别型号的汽车工厂. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:36:37 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class SpecialCarFactory extends AbstractCarFactory{

	/**
	 * 制造特别型号的奥迪车.
	 * @see com.gy.designpattern.abstractfactory.CarFactory#createAudiCar()
	 */
	@Override
	public Car createAudiCar(){

		// TODO Auto-generated method stub
		return super.createCar(CarEnum.AudiSpecialCar);

	}

	/**
	 * 制造特别型号的奔驰车.
	 * @see com.gy.designpattern.abstractfactory.CarFactory#createBenzCar()
	 */
	@Override
	public Car createBenzCar(){

		// TODO Auto-generated method stub
		return super.createCar(CarEnum.BenzSpecialCar);

	}

}
 

好了,主流程走完了,把枚举也贴上:

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:CarEnum <br/>
 * Function: 这是个汽车类型的枚举. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-6 下午3:11:28 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public enum CarEnum {
	AudiNormalCar("com.gy.designpattern.abstractfactory.NormalAudiCar"),
	AudiSpecialCar("com.gy.designpattern.abstractfactory.SpecialAudiCar"),
	BenzNormalCar("com.gy.designpattern.abstractfactory.NormalBenzCar"),
	BenzSpecialCar("com.gy.designpattern.abstractfactory.SpecialBenzCar");

	private String value="";

	private CarEnum(String value){
		this.value=value;
	}

	public String getValue(){
		return this.value;
	}
}

 

好了,boss登场,开始造车:

 

 

package com.gy.designpattern.abstractfactory;
/**
 * ClassName:Boss <br/>
 * Function: Boss决定要造什么车就造什么. <br/>
 * Reason:	 TODO ADD REASON. <br/>
 * Date:     2012-7-9 下午1:26:18 <br/>
 * @author   gongyong
 * @version
 * @since    JDK 1.6
 * @see
 */
public class Boss {
	public static void main(String[] args){
		CarFactory normalCarFactory=new NormalCarFactory();
		CarFactory specialCarFactory=new SpecialCarFactory();
		//生产正常车型的汽车
		Car normalAudiCar=normalCarFactory.createAudiCar();
		Car normalBenzCar=normalCarFactory.createBenzCar();

		//生产特殊车型的汽车
		Car specailAudiCar=specialCarFactory.createAudiCar();
		Car specailBenzCar=specialCarFactory.createBenzCar();

		normalAudiCar.style();
		normalAudiCar.run();
		normalBenzCar.style();
		normalBenzCar.run();

		specailAudiCar.style();
		specailAudiCar.run();
		specailBenzCar.style();
		specailBenzCar.run();

	}

}
 

呼~~我勒个去~终于写完了,好长啊,我都忍不住说一句,抽象工厂方法好麻烦啊,好,回答前面的问题,这个模式这么麻烦,到底有什么好处:是这样的,非常重要的有点就是,工厂模式符合OCP 原则,也就是开闭原则,怎么说呢,比如就车的型号的问题,还有很多其他用途的奔驰车和奥迪车,比如用来飞的,那这个就是要在我们的产品族中增加一类产品,同时再增加一个工厂就可以解决这个问题;还有一个非常大的有点,高内聚,低耦合,在一个较大的项目组,产品是由一批人定义开发的,但是提供其他成员访问的时候,只要提供工厂方法和产品的接口,也就是说只需要提供Product Interface 和抽象工厂,当然也可以提供具体工厂实现,根据实际情况来吧, 就可以产生自己需要的对象和方法。可扩展性很高,当然还有其他优点,自己可以总结,我目前就想到这些了。

   发表时间:2012-08-14  
呵呵,楼主,特殊用途的车到底是什么用途啊,没看明白
0 请登录后投票
   发表时间:2012-11-09  
楼主笔误啊,SpecialBenzCar和 NormalBenzCar  继承错了,应该是extends BenzCar
0 请登录后投票
   发表时间:2012-11-14  
sweetcrying 写道
楼主笔误啊,SpecialBenzCar和 NormalBenzCar  继承错了,应该是extends BenzCar

哈哈,感谢“sweetcrying”,还真是写错了,难得遇见这么认真仔细的同学啊,再次感谢!
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics