`
webcode
  • 浏览: 5941003 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

工厂模式

 
阅读更多

案例场景:有一家汽车工厂,他们生产各类汽车,有小汽车、公交车、摩托车,举例就这三种吧,当生产商需要购买汽车的时候,直接从汽车工厂里面取,具体那些汽车是怎样制造出来的,厂商不用去管,他只需要看到要购买的汽车以及汽车质量有保证即可。在这个场景中用到了我们的简单工厂模式。

在OO设计领域,我们知道前人总结了不少的经验,许多的经验在现代软件工程过程中已经被认为是原则来遵守。下面笔者摘抄几项下文涉及到的OO原则的定义。
OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。我的理解是,对于一个已有的软件,如果需要扩展,应当在不需修改已有代码的基础上进行。
DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程。我的理解是,对于不同层次的编程,高层次暴露给低层次的应当只是接口,而不是它的具体类。

在以前,我们会发现一个现象:比如下面的代码

package cn.com.factor;

//定义一个车的接口
public interface Vehicle {
	public void create();
}

//小轿车的实现类
class Car implements Vehicle{
	@Override
	public void create() {
		System.out.println("生产了一辆小轿车");
	}
}

class Test{
	public static void main(String[] args) {
		Vehicle car=new Car();
		car.create();
	}
}

我们会发现不满足DIP开闭原则,因为客户端在调用的时候,把接口的实现类Car给暴露给了客户端,那么,我们应该怎样解决呢,使用简单工厂方法即可解决。

简单工厂模式:是类的创建模式,又叫做静态工厂方法模式,是由一个工厂对象决定出哪一种产品类的实例,通常它根据自变量的不同返回不同类的实例。

简单工厂方法的实质是由一个工厂类根据传入的参数,动态决定应该创建出哪一个产品类的实例。

简单工厂模式的构成

工厂类角色(Creator):担任这个角色的是简单工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体类实现。

抽象产品(Abstract Product)角色担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。通常使用Java 接口或者抽象Java 类实现这一角色。

具体产品(Concrete Product)角色抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。通常使用具体Java 类实现这个角色。

代码场景模拟:

package cn.com.factor;
//抽象产品角色:定义一个车的接口
public interface Vehicle {
	public void create();
}

package cn.com.factor;
//具体产品角色:小轿车的实现类
public class Car implements Vehicle {
	@Override
	public void create() {
		System.out.println("生产了一辆小轿车");
	}
}

package cn.com.factor;
//具体产品角色:公交车的实现类
public class Bus implements Vehicle {
	@Override
	public void create() {
		System.out.println("生产了一辆公交车");
	}
}

package cn.com.factor;
//具体产品角色:摩托车的实现类
public class MotorCar implements Vehicle {
	@Override
	public void create() {
		System.out.println("生产了一辆摩托车");
	}
}
package cn.com.factor;
//工厂类角色
public class Factory {
	public static Vehicle getVehicle(String str){
		if("小轿车".equals(str)){
			return new Car();
		}
		if("公交车".equals(str)){
			return new Bus();
		}
		if("摩托车".equals(str)){
			return new MotorCar();
		}
		return null;
	}
}

package cn.com.factor;
//测试类
public class Test {
	public static void main(String[] args) {
		//厂家要一辆小轿车
		Vehicle car=Factory.getVehicle("小轿车");
		car.create();
		//厂家要一辆公交车
		Vehicle bus=Factory.getVehicle("公交车");
		bus.create();
		//厂家要一辆摩托车
		Vehicle motor=Factory.getVehicle("摩托车");
		motor.create();
		
	}
}

这样,客户端只要相应的车就可以了,他不可能知道车子是怎样制造出来的,也就是说不知道具体的实现类,工厂只提供了车的一个接口。

我们用OCP看看简单工厂,会发现如果要对系统进行扩展的话治需要增加实现产品接口的产品类(上例表现为“小轿车”,“公交车”类,比如要增加个“电动车”类),而无需对原有的产品类进行修改。这咋一看好像满足OCP,但是实际上还是需要修改代码的——对,就是修改工厂类。上例中如果增加“电动车”产品类,就必须相应的修改“Factory”工厂类,增加个判断。所以可以看出,简单工厂模式是不满足OCP的。这时,我们可以使用抽象工厂模式:

工厂方法模式是对象的创建模式,它是工厂方法模式的进一步推广。假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产品等级结构。那么为了将消费 这些产品对象的责任和创建这些产品对象的责任分割开来,可以引进抽象工厂模式。这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公 用的工厂接口请求所需要的产品。

修改工厂方法模式中的角色

抽象工厂(AbstractFactory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统的商业逻辑无关的。通常使用Java 接口或者抽象Java 类实现,而所有的具体工厂类必须实现这个Java 接口或继承这个抽象Java 类。

具体工厂类(Conrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。通常使用具体Java 类实现这个角色。

修改实例代码:

比如说现在工厂改革了,他又分为小工厂,有专门制造小轿车、专门制造摩托车...

package cn.com.factor;
//增加抽象工厂角色
public interface IFactory {
	public Vehicle getVehicle();
}

package cn.com.factor;
//制造小轿车的工厂
public class CarFactory implements IFactory{
	@Override
	public Vehicle getVehicle() {
		return new Car();
	}
}
package cn.com.factor;
//制造摩托车的工厂
public class MotorFactory implements IFactory {
	@Override
	public Vehicle getVehicle() {
		return new MotorCar();
	}
}
测试:

//让制造小轿车的工厂生产小轿车
IFactory car1=new CarFaactory();
car1.getVehicle();
//让制造摩托车的工厂生产摩托车
IFactory motor1=new MotorFactory();
motor1.getVehicle();

这样,我们便容易拓展和维护我们的代码。

抽象工厂模式

当我们制造车的厂又想制造电脑了,生产各种品牌的电脑,我们就会这样来定义:

//增加抽象工厂角色
public interface IFactory {
 public Vehicle getVehicle();
 public Computer getComputer();//电脑
}
然后写如电脑的一个抽象类以及实现类,这样针对与产品的抽象我们定义为抽象工厂模式,
它对工厂的抽象程度更高。
深入理解:

一:工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放到了一个具体类上.简单工厂是工厂方法模式的特例。
工厂方法模式和抽象工厂模式的最主要的区别在于对工厂的抽象程度上。
抽象工厂模式中一般是抽象出工厂接口,表示他就是一个工厂,而不管它是制造什么产品的工厂,他的抽象程度较高。
而工厂厂
方法模式的抽象工一般是针对于产品进行抽象。表示它是一个生产某类产品的工厂简单工厂是不支持继承的,如果需要建立的对象过多,会使这个类变大,建立偶合性集中在这个类上.
工厂方法解决了简单工厂不支持继承的缺点.
以上两个模式所建立的对象是在一个等级结构中.
抽象工厂是面向多个平行等级结构的,其建立对象的原则是以簇(功能相似的对象)为单位划分需要建立的对象.

二:工厂方法创建一般只有一个方法,创建一种产品。
抽象工厂一般有多个方法,创建一系列产品。 目的不一样工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。 抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。



简单工厂模式与工厂方法模式区别
从以上对两种模式的介绍可以了解到,工厂方法模式是为了克服简单工厂模式的缺点(主要是为了满足OCP)而设计出来的。但是,工厂方法模式就一定比简单工厂模式好呢?笔者的答案是不一定。下面笔者将详细比较两种模式。

1. 结构复杂度
从这个角度比较,显然简单工厂模式要占优。简单工厂模式只需一个工厂类,而工厂方法模式的工厂类随着产品类个数增加而增加,这无疑会使类的个数越来越多,从而增加了结构的复杂程度。

2.代码复杂度
代码复杂度和结构复杂度是一对矛盾,既然简单工厂模式在结构方面相对简洁,那么它在代码方面肯定是比工厂方法模式复杂的了。简单工厂模式的工厂类随着产品类的增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。

3.客户端编程难度
工厂方法模式虽然在工厂类结构中引入了接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是个吸引人的优点。

4.管理上的难度
这是个关键的问题。
我们先谈扩展。众所周知,工厂方法模式完全满足OCP,即它有非常良好的扩展性。那是否就说明了简单工厂模式就没有扩展性呢?答案是否定的。简单工厂模式同样具备良好的扩展性——扩展的时候仅需要修改少量的代码(修改工厂类的代码)就可以满足扩展性的要求了。尽管这没有完全满足OCP,但笔者认为不需要太拘泥于设计理论,要知道,sun提供的java官方工具包中也有想到多没有满足OCP的例子啊(java.util.Calendar这个抽象类就不满足OCP,具体原因大家可以分析下)。
然后我们从维护性的角度分析下。假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得相当麻烦(对号入座已经是个问题了)。反而简单工厂没有这些麻烦,当多个产品类需要修改是,简单工厂模式仍然仅仅需要修改唯一的工厂类(无论怎样都能改到满足要求吧?大不了把这个类重写)。

由以上的分析,笔者认为简单工厂模式更好用更方便些。当然这只是笔者的个人看法而已,毕竟公认的,工厂方法模式比简单工厂模式更“先进”。但有时过于先进的东西未必适合自己,这个见仁见智吧。

分享到:
评论
1 楼 kevenfox 2014-01-15  
生产电脑不应该修改原来的接口,修改的成本太大,这同样不符合开闭原则。

相关推荐

Global site tag (gtag.js) - Google Analytics