设计模式---工厂方法

一.工厂方法定义:
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到子类。

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来实现。(部分解决简单工厂中Switch结构引入的开放修改的问题)

《大话设计模式》给出的“计算器”的例子如下图所示:
这里写图片描述

如上图所示,在客户端(可能是web前端、winform或其他UI)通过用户的操作来决定实例化那种“工厂”。通过“工厂”的统一接口(比如上图中的+CreateOperation)去实例化“产品”。而产品系列又抽象出公共的接口(比如上图中的+GetResult)。这样的好处在于业务代码的编写都是基于抽象接口的:“产品”(比如此例中的算法)的扩展无需修改原服务端的代码(对修改封闭)。只需要新增产品类和对应的工厂类即可(对新增开放)。 一切设计模式都围绕着6大设计原则,其中开放封闭是最重要的原则之一。

二.示例
举的例子为了便于例子,采用的简单明了的案例,不以来任何项目上下文环境。
python示例:

from abc import ABCMeta, abstractmethod

##################################
#服务端代码:
##################################
class CellPhone:
    @abstractmethod
    def make_a_call(self): pass


class AXON(CellPhone):
    def make_a_call(self):
        print("ZTE AXON Calling.....")


class IPhoneX(CellPhone):
    def make_a_call(self):
        print("APPLE IPhoneX Calling.....")


class Vendor:
    @abstractmethod
    def BuildCellPhone(self): pass


class Apple(Vendor):
    def BuildCellPhone(self):
        return IPhoneX()


class ZTE(Vendor):
    def BuildCellPhone(self):
        return AXON()

##################################
#客户端代码:
##################################
Vendors={
        "ZTE": ZTE,
        "APPLE":Apple
         }

vendor_choice =Vendors["APPLE"]()

##################################
#服务端代码-----主业务逻辑
##################################

my_phone = vendor_choice.BuildCellPhone()
my_phone.make_a_call()

ITcl示例:

package require Itcl

#################################################################
#客户端
#################################################################
#相比简单工厂模式,工厂方法模式将Product实例生成的Swicth操作放到了客户端。
set FactorySelect "OnDa"

#选择生产厂家
switch $FactorySelect {

         "Apple" {
                   set Obj_IFactory [Apple #auto]

         }
         "OnDa"    {
                   set Obj_IFactory [OnDa #auto]

         }

}

################################################################
#服务端代码---产品及工厂类定义
################################################################
itcl::class absMP3 {
         protected variable FactoryName   
         public method play
}


itcl::class OnDaMP3 {

         inherit absMP3
         constructor {} {
                   set FactoryName "OnDaMP3"
         }
         public method play {} {
                   puts "$FactoryName play Song!"
         }
}

itcl::class AppleMP3 {

         inherit absMP3
         constructor {} {
                   set FactoryName "AppleMP3"
         }
         public method play {} {
                   puts "$FactoryName play Song!"
         }
}

itcl::class IFactory {

         public method BuildMP3

}

itcl::class OnDa {     
         inherit IFactory
         public method BuildMP3 {} {
                   set Obj_OnDaMP3 [uplevel {namespace which [OnDaMP3 #auto]}]
                   return $Obj_OnDaMP3
         }
}
itcl::class Apple {
         inherit IFactory
         public method BuildMP3 {} {
                   set Obj_AppleMP3 [uplevel {namespace which [AppleMP3 #auto]}]
                   return $Obj_AppleMP3
         }

}



################################################################
#服务端代码---业务逻辑
################################################################
#后续MP3品牌、种类的扩充,不会波及这部分业务逻辑,因为业务逻辑的编码都是基于接口的也就减少了BUG引入的风险,忠实了“开放-封闭”原则。

#生产MP3
set Obj_absMP3 [$Obj_IFactory BuildMP3]
#mp3放歌
$Obj_absMP3 play

PS:设计模式6大原则:

设计模式六大原则(1):单一职责原则
设计模式六大原则(2):里氏替换原则
设计模式六大原则(3):依赖倒置原则
设计模式六大原则(4):接口隔离原则
设计模式六大原则(5):迪米特法则
设计模式六大原则(6):开闭原则

找机会再详细分享,此处不展开解释。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值