写点什么

工厂模式学习

用户头像
en
关注
发布于: 2020 年 12 月 19 日

重温一下工厂模式,作为设计模式的入门,很想将它讲清楚,希望这篇文章能对大家真正的有所帮助。

工厂模式

概述

工厂模式,属于设计模式三大类之一的创建模式里。

其核心思想是提供一个创建对象的超类,允许通过该接口指定创建子类对象的类型。

从go的角度应用的说,工厂模式就是提供一个超类,这个超类有一个创建接口,我们可以通过这个接口获取不同的对象,这些对象实现了同一系列的接口,所以他们可以用同一个interface表示,他们各自实现了这一个interface底下所有的接口,工厂模式的作用就是将他们的创建步骤收敛起来,而创建出来的对象,我们可以叫做工厂的产品。

用户不用管工厂产品的实现是什么,只用管要用哪个产品来处理自己的场景即可。

实现框架

参考:https://refactoring.guru/design-patterns/factory-method

工厂应用场景

1.使用对象类型数目不定,且使用对象针对interface方法的实现各有各的差别(若是一套就没必要用工厂方法来创建不同的对象了),这时候由于工厂模式将产品构建与产品使用的代码分开,在扩展上方便很多,只需要一个新的子类,再实现父类方法就好了。

2.当想节省系统资源时候使用Factory方法,如你想重用已有对象,又希望能在没有相应对象的创建新的对象,这时候将所有同类对象收敛到factory,对于你的搜寻和创建都会简单很多。

3.为库或者框架用户提供拓展其内部组件的方法。

基础库有基础库的对象a,和行为1的实现a1,这时候作为基础库的用户,希望针对行为1做自己的重写覆盖,若是基础库中使用的是工厂模式返回的统一interface,那么作为用户,只需要重写对象u1,实现interface的所有方法,并覆盖行为1,为实现u1,在创建的时候将自己的对象u返回,替换掉a就成功实现了替代。



简单工厂的实现

待修改代码

你有一个披萨店,你的披萨店有orderPizza()函数,用于新建一个披萨,旧的代码如下(此处简化书上的代码)

orderPizze(ptype string)pizza{
Pizza pizza
if ptype=="a"{
pizza = new(apizza)
}else if ptype=="b"{
pizza = new(bpizza)
}
pizza.prepare()
return pizza
}

一般情况,使用函数根据不同类型返回不同的披萨没有问题,但是随着类型新增,我们就要不断的对函数做修改,函数也会越来越大。

简单工厂模式修改实现

将根据不同类型创建不同pizza的行为挪出来,放到另一个对象中,由这个对象专职创建pizza,这个新对象就称作工厂。



解释

在如下代码中

Pizza作为接口(interface),各种不同的pizza(product)可以实现不同的prepare方法

SimplePizzaFactory 是一个具体的工厂对象,他根据ptype的不同创建不同的pizza并返回

PizzaStore是我们的pizza商店,它不再关心pizza的具体诞生,它内含有工厂(可以有不同种类的工厂),每次点单,就将点单的参数传递给工厂,由工厂生产pizza,若工厂无能力生产所需要的pizza则返回空



type Pizza interface {
prepare()
}
type CheesePizza struct {
}
func (s *CheesePizza)prepare(){
fmt.Println("This is cheese pizza.")
}
type SimplePizzaFactory struct{
}
func (s *SimplePizzaFactory)CreatePizza(ptype string)Pizza{
if ptype=="cheese"{
return new(CheesePizza)
}
return nil
}
type PizzaStore struct {
factory SimplePizzaFactory
}
func (s *PizzaStore)PizzaStore(factory SimplePizzaFactory){
s.factory = factory
}
func (s *PizzaStore)orderPizza(ptype string)Pizza{
pizza:=s.factory.CreatePizza(ptype)
if pizza==nil{
return nil
}
pizza.prepare()
return pizza
}
func main() {
factory:=new(SimplePizzaFactory)
pizzaStore:=new(PizzaStore)
pizzaStore.PizzaStore(*factory)
pizzaStore.orderPizza("cheese")
pizzaStore.orderPizza("test")
}



抽象工厂模式

概述

抽象工厂是一种创新的设计模式,可让您生成相关同一族的对象而无需指定其具体类。

实现步骤

1.针对产品系列的每个产品,创建超类接口,各个系列不同产品根据需求实现对应的interface。

2.第二步声明抽象工厂,该接口有所有系列产品的创建方法列表。

3.接着我们根据不同类型,返回不同的工厂对象,同一工厂对象生产的产品就能保证是一个系列的。

个人感觉抽象工厂模式更像是工厂模式的一种变体,只不过将层次往上提了一层,根据不同的类型返回不同的工厂,而工厂早早的根据自己的类型,确定了生产这一系列产品的类型。

应用场景

当您的代码需要使用各种相关产品系列时,可以考虑使用抽象工厂模式。

示例代码

解释

整体流程:

声明获取纽约商店---》从纽约商店点起司披萨---》创建纽约的起司披萨对象---》准备披萨--》由于纽约商店的调料工厂是纽约的---》准备披萨的时候使用调料工厂获取纽约调料---》披萨出炉

//产品面团
type Dough interface {
GetDough()
}
//产品调味
type Sause interface{
GetSause()
}
//具体实现产品1
type NYDough struct{
}
func (s *NYDough)GetDough(){
fmt.Println("this is NYDough")
}
//具体实现产品2
type NYSause struct{
}
func (s *NYSause)GetSause(){
fmt.Println("this is NYSause")
}
//披萨工厂类的声明
type PizzaIngredientFactory interface{
createDough()Dough
createSause()Sause
}
//ny披萨工厂类的声明,可以看到内部已经指定了产品都是ny系列
type NYPizzaIngredientFactory struct{
}
func (s *NYPizzaIngredientFactory)createDough()Dough{
return new(NYDough)
}
func (s *NYPizzaIngredientFactory)createSause()Sause{
return new(NYSause)
}
//披萨的interface
type Pizza interface {
prepare()
getIngredientFactory(PizzaIngredientFactory)
}
type PizzaStore interface {
createPizza()
orderPizza()
}
type NYCheesePizza struct {
pizzaIngredientFactory PizzaIngredientFactory
dough Dough
sause Sause
}
func (s *NYCheesePizza)prepare(){
s.sause = s.pizzaIngredientFactory.createSause()
s.dough = s.pizzaIngredientFactory.createDough()
s.dough.GetDough()
s.sause.GetSause()
fmt.Println("This is NYCheese pizza.")
}
func (s *NYCheesePizza)getIngredientFactory(factory PizzaIngredientFactory){
s.pizzaIngredientFactory = factory
}
//不同地方的经营商,这里是具现化的ny披萨商店
type NYStypePizzaStore struct{
}
func (s *NYStypePizzaStore)CreatePizza(ptype string)Pizza{
pizzaIngredientFactory := new(NYPizzaIngredientFactory)
var pizza Pizza
if ptype=="cheese"{
pizza = new(NYCheesePizza)
//根据披萨的类型获取披萨对应的调料工厂
pizza.getIngredientFactory(pizzaIngredientFactory)
}
return pizza
}
func (s *NYStypePizzaStore)orderPizza(ptype string)Pizza{
var pizza Pizza
if ptype=="cheese"{
pizza = s.CreatePizza(ptype)
pizza.prepare()
}
return pizza
}
func main() {
nyStore:=new(NYStypePizzaStore)
nyStore.orderPizza("cheese")
}

输出

this is NYDough
this is NYSause
This is NYCheese pizza.



参考文章:

https://www.runoob.com/design-pattern/observer-pattern.html

Head First设计模式

https://www.cnblogs.com/yssjun/p/11102162.html

https://refactoring.guru/design-patterns/abstract-factory/go/example

https://refactoring.guru/design-patterns/factory-method



用户头像

en

关注

还未添加个人签名 2018.06.14 加入

还未添加个人简介

评论

发布
暂无评论
工厂模式学习