设计模式之抽象工厂模式

来源:互联网 发布:srt字幕合成软件 编辑:程序博客网 时间:2024/06/07 22:26

        在前面两篇博文中,我记录了简单工厂模式和工厂方法模式这两种设计模式,这两种设计模式用我自己的理解就是:

        简单工厂模式用一个工厂类实现了生产多个不同产品的功能,只要为工厂类提供不同的参数,就可以根据这个参数返回不同的产品,比如加减乘除这四种运算,就是四个不同的产品类,可以为他们抽象出一个共同的基类(或接口),该类(或接口)中定义了这四个类共有的方法getResult(),和运算需要的变量number1、number2,简单工厂模式就是提供一个OperationFactory类,该工厂类提供了一个生产不同运算类的方法createOperator(),通过传不同的参数,返回不同的运算类。

        简单工厂类的应用虽然很广,但是它违反了设计模式中的一个基本原则:开放封闭原则,即设计模式要满足面向扩展开放,面向修改封闭。但是当我们需要增加一个新的运算类时,很明显,工厂类就需要做修改了,createOperator()方法需要根据传入的参数,生成新的运算类。


        为了让简单工厂模式能不违反开放封闭原则,工厂方法模式就产生了。

        工厂方法模式将工厂也抽象出来,而不是像简单工厂模式那样只有一个工厂类,工厂方法模式通过抽象出一个IFactory,将需要生产的不同产品,都为其写不同的工厂类,这些工厂类的基类都是IFactory,这样,如果我们再要增加新的运算类时,就不用修改已有的工厂类了,而是写一个新的工厂类,用于生产这个新的运算类。

        工厂方法模式虽然避免了简单工厂模式违反的开放封闭原则,但是在某些情况下,还是有一定的局限,比如下面的例子:


        数据库中有User表,包含ID和Name字段,针对User的操作,有插入User到数据库和从数据库取对应ID的User这两种,当我们的程序需要从SqlServer数据库切换到Access数据库时,怎么用合理的设计模式让代码能复用呢?如果用工厂方法模式,我们应该这么做:

        1、将对User的操作抽象出来,设计接口IUser,其中包含两个方法的声明:insertUser(User user)、getUser(int id)

        2、为SqlServer和Access分别编写不同的操作类SqlServerUser、AccessUser,且这两个操作类都实现了IUser接口,对User的插入和获取,我们可以使用IUser类来完成,而不必关心到底是哪种数据库了

        3、抽象出一个工厂IFactory,包含方法createUser(),然后分别为SqlServerUser和AccessUser类编写对应的工厂类SqlServerFactory、AccessFactory,由这两个工厂类来生产第二步中的SqlServerUser类和AccessUser类


        到这里基本上就完成了,抽象出来的IUser和IFactory,达到了代码的复用,而且使代码中对数据库的操作,可以不必关心到底是操纵的哪种数据库,上面的模式对应的UML类图如下:


        但是,当我们的数据库中需要增加表的时候,该怎么办呢?如果有一张部门表Department,对部门的操作也有插入和获取这两种,这时候,我们可以在IFactory接口中去声明新的方法createDepartment(),由SqlServerFactory和AccessFactory去复写该方法并生产不同数据库对应的部门操作类,和User一样,对于Department,也要抽象出一个IDepartment接口,声明对Department操作的insert和get方法,这时候,上面的UML类图就变成如下的模式了:



这就是抽象工厂模式。

§模式动机:在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

§抽象工厂模式(Abstract FactoryPattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

抽象工厂模式的优点如下:
§抽象工厂模式的主要优点是隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。
§所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用

抽象工厂模式的缺点如下:
§抽象工厂模式的缺点是在添加新的产品对象时,难以扩展抽象工厂以便生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来很多不便。
§开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)

§在以下情况下可以使用抽象工厂模式:
§一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式重要。
§系统有多于一个的产品族,而客户端只消费其中某一产品族。
§系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

模式结构













0 0
原创粉丝点击