定    义:定义一个用于创建对象的接口,让子类决定实例化那个类

优    点:

             1、良好的封装性,代码结构清晰(调用者只需要知道产品的类名就可以获得该对象)

             2、扩展性非常优秀(在增加产品类的情况下,只要适当地修改具体的工厂类或者扩展一个工厂类)

             3、屏蔽产品类(调用者不关心产品类的如何实现变化,只需要关心产品的接口)

             4、工厂方法模式是典型的解耦框架(高层模块只需要知道产品的抽象类,其他的实现类都不必要关心)

使用场景:

             1、工厂方法模式是new一个对象的替代品,任何需要生成对象的地方都可以使用,但是要在复杂度与便捷之间权衡

             2、需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式,产品不确定,动态变化的非常适合

理      解:根据产品的可变程度来确定是否需要工厂方法模型,因为用工厂模型会增加复杂度,另外一定要注意到工厂方法一定是初始化产品

               的地方,否则工厂方法会变得毫无意义。

实      践:

               先让我们看看工厂方法模型的实现UML图:

 

设计模式利剑一--工厂方法模型_uml

               从女娲造人的故事开始,女娲决定造人了,人又很多种类,白种人,黑种人,黄种人,也许某天女娲突发奇想来一个彩色人中,那么在女娲在设计的时候,很定要考虑到到人种这个产品的扩充性,既然产品的多样性不确定,那么这个就已经符合工厂方法模型的特点了,对于女娲而言,很定不想每想出来一个人,就得自己亲手去捏造这个泥人,那么何必弄一个工厂来批量生产呢?是,这何乐而不为,正因为女娲想到了这点,所以地球上的人口才得以这么昌盛,哈哈。设计的UML图如下所示:

 

设计模式利剑一--工厂方法模型_设计模式_02

      有了如上这个工厂以后,女娲再也不用担心如何制造人的工艺了,而将更多的时间用于更加丰富人类这个产品的个性身上。再来看看生活中我们经常会遇到哪些工厂模式吧,例如每个月灌煤气的问题,自己去弄,首先很辛苦,很费劲,而且煤气公司间隔一段时间会更换地理位置,价格也是会有不断的变化,我想购买到价格最低最优惠的煤气那真的是很辛苦,而现在物业公司也提供了这种代灌煤气的服务,那么经过设计的UML图如下所示:

            

设计模式利剑一--工厂方法模型_dotnetnuke_03

 经过上图的设计以后,我以后再也不用操心如何来应付日益变化的煤气公司不断变化的价格以及位置变化,我只需要告诉物业公司给我找A煤气公司送煤气,而不需要知道具体的过程了,如果哪天A煤气公司价格不合理,我可以随时换B煤气公司,这就是工厂模式的好处,上图举的例子是工厂模型的扩展,简单工厂模式。

             而在系统中让我最觉得工厂模型使用的出神入化的则是在数据库连接层的设计上,考虑到自己的项目可能随着服务器的不同类型而可能会换成JDBC,MYSQL,SQL Server,Oracle等类型,下面来看看我项目中实现数据连接层的设计方法,这也是参考DotNetNuke的数据连接层的模式:

    

设计模式利剑一--工厂方法模型_产品_04

    上面的设计模式非常的利于扩充,那天项目要求我将现在SQL连接全部换成JDBC,我新增加一个类,然后在所有获得数据的地方更改名称即可,非常的方便。上面这个设计还是比较复杂的,属于多个工厂类的模型,每个产品都对应一个工厂,这样非常符合单一职责原则。

 

         现在来看看女娲造人的代码实现:

Public MustInherit Class AbstractHumanFactory
Public MustOverride Function createHuman(ByVal type As System.Type) As Human
End Class ' AbstractHumanFactory
Public Class HumanFactory
Inherits AbstractHumanFactory
Public Overrides Function createHuman(ByVal type As System.Type) As Human
Dim newhuman As Human = Nothing
Try
Dim ci As Reflection.ConstructorInfo = type.GetConstructor(System.Type.EmptyTypes)
newhuman = CType(ci.Invoke(Nothing), Human)
'Activator.CreateInstance
Catch ex As Exception
End Try
Return newhuman
End Function

End Class ' HumanFactory

  再来看看产品类:

Public Interface Human

Sub getColor()
Sub talk()
End Interface ' Human
Public Class BlackHuman
Implements Human

Public Sub getColor() Implements Human.getColor
Console.WriteLine("黑色人种皮肤是黑色的")
End Sub
Public Sub talk() Implements Human.talk
Console.WriteLine("黑色人种说的都是英文")
End Sub

End Class ' BlackHuman
Public Class WhiteHuman
Implements Human

Public Sub getColor() Implements Human.getColor
Console.WriteLine("白色人种的皮肤是白色的")
End Sub
Public Sub talk() Implements Human.talk
Console.WriteLine("白色人种的语言说的是英文")
End Sub

End Class ' WhiteHuman
Public Class YellowHuman
Implements Human

Public Sub getColor() Implements Human.getColor
Console.WriteLine("黄种人皮肤是黄色的")
End Sub
Public Sub talk() Implements Human.talk
Console.WriteLine("黄种人说的都是中国话")
End Sub

End Class ' YellowHuman

 

Module Nvwa
Sub Main()
'先申明工厂
Dim _factory As HumanFactory = New HumanFactory()
Console.WriteLine("女娲开始造人")
Dim _whiteHuman As WhiteHuman = _factory.createHuman(Type.GetType("工厂模式.WhiteHuman"))
_whiteHuman.getColor()
_whiteHuman.talk()
Dim _YellowHuman As YellowHuman = _factory.createHuman(Type.GetType("工厂模式.YellowHuman"))
_YellowHuman.getColor()
_YellowHuman.talk()
Dim _BlackHuman As BlackHuman = _factory.createHuman(Type.GetType("工厂模式.BlackHuman"))
_BlackHuman.getColor()
_BlackHuman.talk()
Console.Read()
End Sub
End Module