当前位置:首页 > > 充电吧
[导读]工厂模式介绍                                   一、引子       话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)看

工厂模式介绍        

                          一、引子
       话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)看来这人比较爱国,没有日本车),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi后他说“开奥迪车!”。
       你一定说:这人有病!直接说开车不就行了?!
       而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!
       幸运的是,这种有病的现象在OO语言中可以避免了。下面以Java语言为基础来引入我们本文的主题:工厂模式!!

  二、简介
        工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:
                1. 简单工厂模式(Simple Factory)                
                2. 工厂方法模式(Factory Method)
                3. 抽象工厂模式(Abstract Factory)
        这三种模式从上到下逐步抽象,并且更具一般性。
        还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。两者皆可,这本为使用《Java与模式》的分类方法。
        在什么样的情况下我们应该记得使用工厂模式呢?大体有两点:
                1.在编码时不能预见需要创建哪种类的实例。
           2.系统不应依赖于产品类实例如何被创建、组合和表达的细节
         工厂模式能给我们的OOD、OOP带来哪些好处呢??
        等我们讲完后,大概你就能知道了       

  三、简单工厂模式
        顾名思义,这个模式本身很简单,而且使用在业务较简单的情况下。
        它由三种角色组成:
                工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
                抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
                具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
        来用类图来清晰的表示下的它们之间的关系(如果对类图不太了解,请参考我关于类图的文章):
                                
        那么简单工厂模式怎么用呢?我来举个例子吧,我想这个比讲一大段理论上的文字描述要容易理解的多!下面就来给那个暴发户治病 : P
        在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:“开车”就可以了。来看看怎么实现的:
//抽象产品角色
•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 ");                        • }                                                •                                                •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。本程序在jdk1.4 下运行通过。
      程序中各个类的关系表达如下:

}
。。。(奥迪我就不写了:P)

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

 四、工厂方法模式
        先来看下它的组成吧:
                    抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
                    具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
                    抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
                    具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在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)                        •{                        •}                        •}                        •}                                                        工厂方法使用一个抽象工厂角色作为核心来代替在简单工厂模式中使用具体类作为核心。让我们来看看工厂方法模式给我们带来了什么?使用开闭原则来分析下工厂方法模式。当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。看来,工厂方法模式是完全符合开闭原则的!
        使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
        当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族(下一节将解释这个名词)。那么这种情况下就可能可以使用抽象工厂模式了。

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

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

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

七、总结  
      这是我对工厂模式学习的一个巩固,并且提出了一些自己的认识和想法。毕竟本人才疏学浅,难免有理解错和肤浅的地方,希望高人能指正,并且希望能给大家带来帮助

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭