标签:设计模式 工厂模式
1.首先提一下,面向对象三大特性:封装、继承、多态;两大基本原则:单一职责原则和开放封闭原则。这些是最基本的,如果觉得不熟悉,请百度,在此不赘述。
2.工厂模式分三种:1)简单工厂模式,2)工厂方法模式,3)抽象工厂模式。这三种模式从上到下逐步抽象,并且更具一般性。
3.工厂模式的适用情况:
1) 在编码时不能预见需要创建哪种类的实例
2) 系统不应依赖于产品类实例如何被创建、组合和表达的细节。
4.简单工厂:由三种角色组成,1)工厂类角色,这是这个模式的核心,还有一定的业务逻辑和判断逻辑。它往往由一个具体的类来实现。2)抽象产品角色,它一般是具有产品继承的父类或者实现的接口。一般由接口或者抽象类来实现。3)具体产品角色,工厂类所创建的对象就是此角色的实例,一般由一个类来实现。
其逻辑关系如下图:
案例:话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)看来这人比较爱国,没有日本车),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!",坐上Bmw后他说"开宝马车!",坐上Audi后他说"开奥迪车!"。你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是,这种有病的现象在OO语言中可以避免了。
在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:"开车"就可以了。来看看怎么实现的:
//抽象产品角色
publicinterface Car{
publicvoid drive();
}
//具体产品角色
publicclass Benz implements Car{
publicvoid drive() {
System.out.println("Driving Benz ");
}
}
publicclass Bmw implements Car{
publicvoid drive() {
System.out.println("Driving Bmw ");
}
}
。。。(奥迪我就不写了:P)
//工厂类角色
publicclass Driver{
//工厂方法
//注意 返回类型为抽象产品角色
publicstatic Car driverCar(String s)throws Exception {
//判断逻辑,返回具体的产品角色给Client
if(s.equalsIgnoreCase("Benz")) returnnew Benz();
elseif(s.equalsIgnoreCase("Bmw"))
returnnew Bmw();
......
elsethrownew Exception();
。。。
//欢迎暴发户出场......
publicclass Magnate{
publicstaticvoid main(String[] args){
try{
//告诉司机我今天坐奔驰
Car car = Driver.driverCar("benz");
//下命令:开车
car.drive();
。。。
如果将所有类放入一个文件中,那么最后最有Driver这个类被声明为public。这便是简单工厂模式,其好处有:
1) 使用了简单工厂模式后,客户端免除了直接创建产品的责任,而仅仅负责“消费”产品,(正如暴发户所为)。
2) 从开闭原则的角度来说,当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类,就可以被客户使用了。对于产品来说,它是符合开闭原则的;但对于工厂不太理想,因为每增加一辆车,都要在工厂类中增加业务逻辑和判断逻辑,这显然是违背开闭原则的。
3) 对于这样的工厂类(例子中的司机师傅),我们称它为全能类或者是上帝类。
5.建议:我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了,进而累坏了我们可爱的程序员
正如我前面提到的简单工厂模式适用于业务将简单的情况下。而对于复杂的业务环境可能不太适应阿。这就应该由工厂方法模式来出场了!!
6.工厂模式:组成,1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。一般由抽象类或者接口来实现。2)具体工厂角色,它还有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象,一般由具体的类来实现。3)抽象产品角色,它是具体产品继承的父类或者实现的接口。一般由抽象类或者接口来实现。4)具体产品角色:具体工厂所创建的对象就是此角色的实例。一般由具体的类来实现。
由上述可知,工厂模式就是在简单模式的基础上又新增量对工厂的抽象。
7.案例:话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:看你跟我这么多年的份上,以后你不用这么辛苦了,我给你分配几个人手,你只管管好他们就行了!于是,工厂方法模式的管理出现了。代码如下:
//抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。 //抽象工厂角色 public interface Driver{ public Car driverCar(); } public class BenzDriver implements Driver{ public Car driverCar(){ return new Benz(); } } public class BmwDriver implements Driver{ public Car driverCar() { return new Bmw(); } } ......//应该和具体产品形成对应关系,这里略... //有请暴发户先生 public class Magnate { public static void main(String[] args) { try{ Driver driver = new BenzDriver(); Car car = driver.driverCar(); car.drive(); }catch(Exception e) { } } }
8.工厂方法使用一个抽象工厂角色作为核心来代替在简单工厂模式中使用具体类作为核心。工厂模式的好处有:使用开闭原则来分析下工厂方法模式。当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。看来,工厂方法模式是完全符合开闭原则的!
9.建议:使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族,那么这种情况下就可能可以使用抽象工厂模式了。
10.小结:让我们来看看简单工厂模式、工厂方法模式给我们的启迪:
如果不使用工厂模式来实现我们的例子,也许代码会减少很多--只需要实现已有的车,不使用多态。但是在可维护性上,可扩展性上是非常差的(你可以想象一下,添加一辆车后要牵动的类)。因此为了提高扩展性和维护性,多写些代码是值得的。
11.抽象工厂模式:产品族,位于不同产品等级结构中,功能相关联的产品组成的家族。比如,BmwCar和BenzCar就是两个产品树(产品层次结构)。而BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzSportsCar也是一个产品族。
回到抽象产品模式的话题上,可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足以下条件:
1)系统中有多个产品族,而系统一次只可能消费其中一族产品
2)同属于同一个产品族的产品一起使用时。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
看过了前两个模式,对这个模式各个角色之间的协调情况应该心里有个数了,我就不举具体的例子了。只是一定要注意满足使用抽象工厂模式的条件哦,不然即使存在了多个产品树,也存在产品族,但是不能使用的。
参考文章:http://www.cnblogs.com/poissonnotes/archive/2010/12/01/1893871.html
本文出自 “虎哥的博客” 博客,请务必保留此出处http://7613577.blog.51cto.com/7603577/1587209
标签:设计模式 工厂模式
原文地址:http://7613577.blog.51cto.com/7603577/1587209