工厂类模式

浏览 594

课文

### 工厂方法模式(Factory Method Pattern) **情景** 某家游戏店里售卖任天堂和索尼的产品,写成代码如下: ```python # 定义若干个商品类(Switch等),每调用一次create_good相当于返回一个商品 class Switch: def create_good(self): return "Switch游戏机" class Zelda: def create_good(self): return "塞尔达" class PS5: def create_good(self): return "PS5游戏机" class TLOU: def create_good(self): return "最后生还者" ``` 店里有一位叫小明的店员,他会询问顾客想要什么东西,并从货架上翻出来: ```python # 定义一个店员类,拥有一个搜索方法,并返回一个实例: class Clerk: def search(self, goods): # 考虑到可能对于商品的大小写标准不同意,将输入的字符串转化成小写,并定义一个字典进行对比 goods = goods.lower() dic = {"ps5": PS5, "switch": Switch, "tlou": TLOU, "Zelda": Zelda} return dic[goods]() ``` 今天小红来到店里,让小明给她拿一台 PS5,打算趁着假期玩一玩别人送的最后生还者: ```python xiaoming = Clerk() ps5 = xiaoming.search("PS5") print(ps5.create_good()) ``` 输出: ```output PS5游戏机 ``` 这就是最简单的工厂方法模式的流程。 **正文** 《设计模式》一书中,对工厂方法模式的描述是:**定义一个用于创建对象的接口,让子类决定实例化哪一个类**。怎么理解这段描述呢? 我们可以考虑将上面的例子套进去。例子中,店员类(Clerk)的`search()`方法即「创建对象的接口」,子类则是 Switch、PS5 等商品类,商品类中`create_good()`方法返回的字符串("PS5 游戏机"等)则作为「子类实例化的类」代替。 这时候聪明的同学要问了:我完全可以考虑跳过店员自己找到商品,为什么还要多此一举呢? 其实这是个设计模式的初学者都会有的疑问。因为在实际开发过程中,更多的情况不会像举例一样这么简单就能调用一个对象,而是需要:做一些初始化工作、调取用户输入、获取一些参数进行业务逻辑判断……等等,完成这些工作之后才能够创建并调用对象,但我们不希望这些东西暴露给客户端。就像平时买东西,只需要知道跟店员要这个东西,他就会拿出来,中间的生产、运输、仓储等等工作我们毫不关心。这就是工厂方法模式最大的意义,将创建对象的业务逻辑与调用剥离开,客户端只需要知道调用封装好的方法就能获取相应的对象,免去重写这部分代码的过程。 通常,我们将定义接口的类统称抽象工厂类,各个子类统称为具体工厂类,子类所实例化的类统称为产品类。 ### 抽象工厂模式(Abstract Factory Pattern) **情景** 将上述工厂方法模式的情景稍微做一下变更:游戏店里分为任天堂区和索尼区,每个区都卖游戏机和游戏: ```python class Nintendo: def create_console(self): return "Switch游戏机" def create_game(self): return "塞尔达传说" class SONY: def create_console(self): return "PS5游戏机" def create_game(self): return "最后生还者" ``` 同样提供小明,不过稍微做些变动: ```python class Clerk: def search(self, VendorCls): VendorCls = VendorCls.lower() dic = { "sony": SONY, "nintendo": Nintendo, } self.vendor = dic[VendorCls] def show(self): vendor = self.vendor() console = vendor.create_console() game = vendor.create_game() print(console + "能玩" + game) ``` 小花是一名认真刻苦的学生,之前从未接触过游戏,最近在微博上被人种草了 Switch 游戏机,但不知道任天堂有什么游戏,于是她咨询了店员: ```python xiaoming = Clerk() xiaoming.search("nintendo") xiaoming.show() ``` 输出: ```output Switch游戏机能玩塞尔达传说 ``` 这就是抽象工厂模式。 **正文** 抽象工厂模式**提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类**。同样套用上面的例子: - 「Switch 游戏机」和「塞尔达传说」就是定义中「相互依赖的对象」(属于同等厂商的不同产品),称为一个**产品族**,同理 「PS5 游戏机」和 「最后生还者」也是一个产品族;而 「Switch 游戏机」与 「PS5 游戏机」、「塞尔达传说」 类与「最后生还者」属于不同厂商的同等产品,称为一个**产品等级**; - Nintendo 类和 SONY 类则是定义中的「具体的类」,分别提供了`create_console()`方法和`create_game()`方法去返回对应产品族中同一产品等级结构的产品; - Clerk 类中的`search()`方法则是「接口」,它同样封装了一些业务逻辑,根据业务逻辑就能返回对应的具体的类。 实际上,抽象工厂模式与工厂方法模式非常相似,但其具体工厂类拥有多于一个返回实例的方法,而工厂方法模式只有一个。但它们的本质是一样的:客户端根据需要调用工厂类,工厂类根据相应逻辑返回对应的对象,这就是工厂模式的本质。

实战

1.以上面抽象工厂模式的代码为基础,增加一个微软分区,能够返回「Xbox游戏机」、「光环」 2.以习题1的代码为基础,扩增工厂的产品等级,分别返回「Switch Pro手柄」、「PS5 DS5手柄」以及「Xbox精英手柄」

解析

1.以上面抽象工厂模式的代码为基础,增加一个微软分区,能够返回 Xbox、HALO 的实例 ```python class Microsoft: def create_console(self): return "Xbox游戏机" def create_game(self): return "光环" ``` 2.以习题 1 的代码为基础,扩增工厂的产品等级,分别返回“Switch Pro 手柄”,“PS5 DS5 手柄”和“Xbox 精英手柄”。 ```python class Microsoft: ... def create_gamepad(self): return "Xbox精英手柄" class Nintendo: ... def create_gamepad(self): return "Switch Pro手柄" class SONY: ... def create_gamepad(self): return "PS5 DS5手柄" ``` ```~~~~
点击查看

评论

登录参与讨论

暂无评论

共 0 条
  • 1
前往
  • 1