设计模式-工厂方法模式(Go实现)

 

目录

  • 工厂方法模式
  • 需求
  • 修改前
    • 简单工厂设计
    • 代码
  • 修改后
    • 工厂方法设计
    • 代码
  • 测试
    • 测试代码
    • 结果
  • 总结
    • 适用场景
    • 优势
    • 缺点
  • 参考

 

工厂方法模式

定义一个用于建立对象的接口,让子类决定将哪个类实例化。再也不提供一个统一的工厂类来建立全部的产品对象,而是针对不一样的产品提供不一样的工厂,系统提供一个与产品等级结构对应的工厂等级结构。
工厂方法模式四要素:数据库

  • 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来做为与调用者交互的接口,其本质上是同样的。
  • 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,须要有多少种产品,就须要有多少个具体的工厂实现。
  • 产品接口。产品接口的主要目的是定义产品的规范,全部的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。一样,产品接口也能够用抽象类来代替,但要注意最好不要违反里氏替换原则。
  • 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。
需求

快餐店的食物,目前有汉堡,粥,须要向顾客展现价格。编程

修改前

简单工厂设计

在这里插入图片描述
缺点
添加食物时须要修改工厂类FoodsFactory的方法GetFoodide

代码

package SimpleFactory

import (
	"fmt"
)

type Foods interface {
	Display()
}

type Hamburger struct {
	price int
}

func (h Hamburger) Display() {
	fmt.Println("I'm Hamburger, price is ",h.price)
}

type Porridge struct {
	price int
}

func (p Porridge) Display() {
	fmt.Println("I'm Porridge, price is ",p.price)
}

type FoodsFactory struct {

}

func (f FoodsFactory)GetFood(name string) Foods {
	switch name {
	case "hamburger":
		return & Hamburger{price: 10}
	case "porridge":
		return &Porridge{price: 8}
	default:
		return nil
	}
}
修改后

工厂方法设计

在这里插入图片描述
优势
添加食物时,添加一个类和对应的具体工厂方法便可,不须要修改源代码测试

代码

package FactoryMethod
import (
	"fmt"
)

type Foods interface {
	Display()
}

type Hamburger struct {
	price int
}

func (h Hamburger) Display() {
	fmt.Println("I'm Hamburger, price is ",h.price)
}

type Porridge struct {
	price int
}

func (p Porridge) Display() {
	fmt.Println("I'm Porridge, price is ",p.price)
}

type FoodsFactory interface {
	GetFood()
}

type HamburgerFactory struct {

}
func (h HamburgerFactory)GetFood() Foods {
	return & Hamburger{price: 10}
}

type PorridgeFactory struct {

}

func (p PorridgeFactory)GetFood() Foods {
	return &Porridge{price: 8}
}
测试

测试代码

package FactoryMethod

import "testing"

func TestMethod(t *testing.T) {
	h := HamburgerFactory{}
	ham := h.GetFood()
	ham.Display()
	p := PorridgeFactory{}
	por := p.GetFood()
	por.Display()
}

结果

=== RUN TestMethod
I’m Hamburger, price is 10
I’m Porridge, price is 8
— PASS: TestMethod (0.00s)
PASS设计

总结

适用场景

  • 客户端不知道它所须要的对象的类。在工厂方法模式中,客户端不须要知道具体产品类的类名,只须要知道所对应的工厂便可,具体的产品对象由具体工厂类建立,可将具体工厂类的类名存储在配置文件或数据库中。
  • 抽象工厂类经过其子类来指定建立哪一个对象。在工厂方法模式中,对于抽象工厂类只须要提供一个建立产品的接口,而由其子类来肯定具体要建立的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

优势

  • 无须知道具体产品类的类名。工厂方法用来建立客户所须要的产品,同时还向客户隐藏了哪一种具体产品类将被实例化这一细节,用户只须要关心所需产品对应的工厂,无须关心建立细节。对象

  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它可以让工厂能够自主肯定建立何种产品对象,而如何建立这个对象的细节则彻底封装在具体工厂内部。工厂方法模式之因此又被称为多态工厂模式,就正是由于全部的具体工厂类都具备同一抽象父类。blog

  • 在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其余的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就能够了,这样,系统的可扩展性也就变得很是好,彻底符合“开闭原则”。接口

缺点

  • 在添加新产品时,须要编写新的具体产品类,并且还要提供与之对应的具体工厂类,系统中类的个数将成对增长,在必定程度上增长了系统的复杂度,有更多的类须要编译和运行,会给系统带来一些额外的开销。
  • 因为考虑到系统的可扩展性,须要引入抽象层,在客户端代码中均使用抽象层进行定义,增长了系统的抽象性和理解难度,且在实现时可能须要用到反射等技术,增长了系统的实现难度。
相关文章
相关标签/搜索