Go实现设计模式--工厂模式

5 篇文章 0 订阅

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

工厂模式

概述

工厂模式,属于设计模式三大类之一的创建模式里。
其核心思想是提供一个创建对象的超类,允许通过该接口指定创建子类对象的类型。
从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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值