`
meilididiao
  • 浏览: 1986 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

浅谈工厂模式

 
阅读更多
一、简介
工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:
1.
简单工厂模式(Simple Factory)
2.
工厂方法模式(Factory Method)
3.
抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。下面是使用工厂模式的两种情况:
1.
在编码时不能预见需要创建哪种类的实例。
2.
系统不应依赖于产品类实例如何被创建、组合和表达的细节
 
三、简单工厂模式
顾名思义,这个模式本身很简单,而且使用在业务较简单的情况下。
它由三种角色组成(关系见下面的类图):
1、工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
2、抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
3、具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

那么简单工厂模式怎么用呢?我来举个例子吧,我想这个比讲一大段理论上的文字描述要容易理解的多!
在使用了简单工厂模式后,现在人只需要坐在车里对司机说句:"开车"就可以了。来看看怎么实现的:
//
抽象产品角色
public interface Car{
public void drive();
}

//具体产品角色
public class Benz implements Car{
public void drive() {
System.out.println("Driving Benz ");
}
}

public class Bmw implements Car{
public void drive() {
System.out.println("Driving Bmw ");
}
}
。。。(奥迪我就不写了:P

//工厂类角色
public class Driver{

//工厂方法
//
注意 返回类型为抽象产品角色
public static Car driverCar(String s)throws Exception {

//判断逻辑,返回具体的产品角色给Client
if(s.equalsIgnoreCase("Benz")) return new Benz();
else if(s.equalsIgnoreCase("Bmw"))
return new Bmw();

......
else throw new Exception();
。。。

//欢迎出场......
public class Magnate{
public static void main(String[] args){
try{
//
告诉司机我今天坐奔驰
Car car = Driver.driverCar("benz");
//
下命令:开车
car.drive();
。。。
如果将所有的类放在一个文件中,请不要忘记只能有一个类被声明为public
程序中类之间的关系如下:

这便是简单工厂模式了。下面是其好处:
首先,使用了简单工厂模式后,我们的程序不在"有病",更加符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责"消费"产品(正如暴发户所为)。
下面我们从开闭原则上来分析下简单工厂模式。当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。那么对于产品部分来说,它是符合开闭原则的--对扩展开放、对修改关闭;但是工厂部分好像不太理想,因为每增加一辆车,都要在工厂类中增加相应的商业逻辑和判断逻辑,这显自然是违背开闭原则的。
对于这样的工厂类(在我们的例子中是为司机师傅),我们称它为全能类或者上帝类。
我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了,进而累坏了我们可爱的程序员:(
正如我前面提到的简单工厂模式适用于业务将简单的情况下。而对于复杂的业务环境可能不太适应阿。这就应该由工厂方法模式来出场了!!

四、工厂方法模式
先来看下它的组成吧:
1、抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2、具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
3、抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4、具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
来用类图来清晰的表示下的它们之间的关系:


我们还是老规矩使用一个完整的例子来看看工厂模式各个角色之间是如何来协调的。话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:看你跟我这么多年的份上,以后你不用这么辛苦了,我给你分配几个人手,你只管管好他们就行了!于是,工厂方法模式的管理出现了。代码如下:
//
抽象产品角色,具体产品角色与简单工厂模式类似,只是变得复杂了些,这里略。
//
抽象工厂角色
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)
{ }
}
}
工厂方法使用一个抽象工厂角色作为核心来代替在简单工厂模式中使用具体类作为核心。让我们来看看工厂方法模式给我们带来了什么?使用开闭原则来分析下工厂方法模式。当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。看来,工厂方法模式是完全符合开闭原则的!
使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族,那么这种情况下就可能可以使用抽象工厂模式了。

五、小结
让我们来看看简单工厂模式、工厂方法模式给我们的启迪:
如果不使用工厂模式来实现我们的例子,也许代码会减少很多--只需要实现已有的车,不使用多态。但是在可维护性上,可扩展性上是非常差的(你可以想象一下,添加一辆车后要牵动的类)。因此为了提高扩展性和维护性,多写些代码是值得的。

六、抽象工厂模式
先来认识下什么是产品族:位于不同产品等级结构中,功能相关联的产品组成的家族。如果光看这句话就能清楚的理解这个概念,我不得不佩服你啊。还是让我们用一个例子来形象地说明一下吧。

图中的BmwCarBenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCarBmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCarBenzSportsCar也是一个产品族。
回到抽象产品模式的话题上,可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:
1.
系统中有多个产品族,而系统一次只可能消费其中一族产品
2.
同属于同一个产品族的产品以其使用。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

 

看过了前两个模式,对这个模式各个角色之间的协调情况应该心里有个数了,我就不举具体的例子了。只是一定要注意满足使用抽象工厂模式的条件哦,不然即使存在了多个产品树,也存在产品族,但是不能使用的。

分享到:
评论

相关推荐

    浅谈PPP模式下的工程造价管理

    浅谈PPP模式下的工程造价管理

    浅谈工程管理信息化应用模式.doc

    浅谈工程管理信息化应用模式.doc

    【ZLG微信文档精选】浅谈工程师的调试法宝(三)——SWO引脚的巧妙应用.pdf

    完成这些配置后,当程序进入调试模式时,通过设置Keil工程的调试选项,选择Trace的配置,然后在调试界面中打开“Serial Windows”下的“Debug (printf) Viewer”,就能实时看到MCU通过SWO引脚发送到编译器的打印信息...

    浅谈在ppp模式下公路工程经营成本管理

    浅谈在ppp模式下公路工程经营成本管理

    【ZLG微信文档精选】浅谈工程师的调试法宝(1-5).zip

    - 半主机模式是一种让嵌入式系统与主机进行通信的调试技术,常用于模拟某些硬件功能,如I/O操作。 - 在这种模式下,嵌入式应用的部分任务依赖于主机操作系统,如文件读写、时间管理等。 - 设置半主机调试需要在...

    浅谈C#设计模式之工厂模式

    浅谈C#设计模式之工厂模式 本文主要介绍了C#设计模式中的一种重要模式:工厂模式。工厂模式是一种创造型模式,提供了一种创建对象的方式,旨在解决继承和多态性的问题。 工厂模式的定义 工厂模式是指定义一个用于...

    浅谈EPC模式的优势.doc

    EPC模式,全称为Engineering Procurement Construction,即设计-采购-施工模式,是工程总承包的一种典型形式。在EPC模式中,承包商负责项目的全过程,包括设计、设备和材料的采购以及施工,甚至包括后期的调试和试...

    设计模式浅谈种PPT学习教案.pptx

    本PPT学习教案深入浅谈了设计模式的基本概念和重要原则,同时介绍了几种创建型设计模式。 首先,设计模式产生的原因通常是因为代码的紧密耦合,如对特定类的依赖、硬件和软件平台的依赖、对象表示和实现的依赖等。...

    浅谈IPD管理模式在复杂工程项目中的应用.pdf

    【IPD管理模式】,即Integrated Project Delivery,是一种先进的综合管理模式,尤其适用于大型、群体和复杂的工程项目。IPD强调的是在项目早期就集合所有关键参与者,包括设计方、施工方、业主等,形成一个协同工作...

    浅谈电子信息工程专业人才培养模式分析与实践.pdf

    浅谈电子信息工程专业人才培养模式分析与实践.pdf

    浅谈工程量清单模式下的招投标报价.doc

    在工程招投标过程中,工程量清单计价模式是国际通用的标准做法,也是国内建筑市场日益推崇的方式。这种模式强调了投标方需对工程量清单的精确性和合理性负责,从而确保公平竞争和项目的经济效益。本文将深入探讨如何...

    浅谈工程管理信息化应用模式.docx

    【工程管理信息化应用模式】 随着信息技术的飞速发展,工程管理信息化已经成为提升建筑行业效率和质量的关键手段。本文主要探讨了工程管理信息化应用的现状及其存在的问题,并提出了相应的应用模式和改进措施。 **...

    软件体系结构Builder模式浅谈

    在软件工程中,当需要创建的对象具有多个可变组成部分时,Builder模式能够帮助我们构造这些对象,同时保持构建算法的稳定,即使对象的各个部分在不断变化。 Builder模式通常由四个主要角色组成: 1. 抽象Builder...

    浅谈EPC工程总承包管理模式.docx

    【EPC工程总承包管理模式概述】 EPC(Engineering-Procurement-Construction)工程总承包管理模式是一种集设计、采购、施工于一体的工程管理方式,旨在解决设计、采购、施工相互制约的问题,提高项目管理水平,确保...

    设计模式浅谈24种.ppt

    在《设计模式浅谈24种》中,主要讨论了24种经典的GOF设计模式,这些模式被分为三大类:创建型、结构型和行为型。 创建型模式主要关注对象的创建,包括以下几个核心模式: 1. **Abstract Factory**(抽象工厂)模式...

    浅谈设计模式在Android代码重构中的应用.pdf

    文章通过具体的Android应用开发案例,展示了如何运用设计模式进行代码重构,例如,通过使用单例模式管理网络请求,使用工厂模式简化对象创建,使用观察者模式实现数据的实时更新等。 5. 提升信息素养的重要性 在...

    【ZLG微信文档精选】浅谈工程师的调试法宝(二)——半主机的巧妙应用.pdf

    接着,需要对工程进行特定配置,以启用半主机模式。配置完成后,进入调试模式,并打开TerminalI/O窗口。运行程序后,可以看到输出信息和用户输入的字符。 尽管半主机技术在某些方面非常有用,但它存在一些局限性,...

Global site tag (gtag.js) - Google Analytics