写点什么

设计模式 -- 策略模式与工厂模式

用户头像
en
关注
发布于: 刚刚
设计模式--策略模式与工厂模式

前言

笔者之前有系统学习了一下设计模式,前段时间跟同事聊天中发现对于工厂模式和策略模式的概念还是有些不清晰,在此带着问题,针对策略模式和工厂模式再次进行一遍梳理,希望能对大家的学习有所帮助。(其中的实现代码均为 go 语言书写)

一.简介

所有设计模式都可以按其意图或目的进行分类。三组主要模式如下:

  • 创建模式提供了对象创建机制,可以提高现有代码的灵活性和重用性。

  • 结构模式解释了如何将对象和类组装成更大的结构,同时保持结构的灵活性和效率。

  • 行为模式负责有效的沟通和对象之间的责任分配。

我们今天要介绍的工厂模式属于创建模式的一种,策略模式属于行为模式的一种。

二.工厂模式

2.1 核心思想

工厂方法是一种创建型设计模式,它提供了在超类中创建对象的接口,但允许子类更改将要创建的对象的类型。

2.2 实现框架


1.product 定义了通用的 interface 接口

2.concrete product 代指特殊的具体产品,他们实现了共同的 interface,但每个的实现方式不一致

3.creator 声明工厂方法,返回类型与产品匹配的对象

4.ConcreteCreator 返回不同类型的产品

2.3 简单工厂的实现

2.3.1 一般实现

以披萨店为例子,披萨店有点单披萨的需求,一个披萨店里面会有多个类型的披萨,如 a,b 等类型,若是不使用设计模式,每次用户点单披萨的代码书写如下

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

随着披萨类型的增加,代码也会不可避免的增加,从而导致冗余,可读性差等问题。

2.3.2 工厂模式实现

以披萨店的例子,应用工厂模式,我们将创建不同类型披萨的行为抽象出来,根据工厂模式的架构,设计代码如下

interface

type Pizza interface {	prepare()}
复制代码

产品 a concrete product

type CheesePizza struct {
}
func (s *CheesePizza)prepare(){ fmt.Println("This is cheese pizza.")}
复制代码

工厂 ConcreteCreator

type SimplePizzaFactory struct{}
func (s *SimplePizzaFactory)CreatePizza(ptype string)Pizza{ if ptype=="cheese"{ return new(CheesePizza) } return nil}
复制代码

披萨店应用 creator

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)//工厂模式,根据披萨的type创建不同的披萨对象 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")}
复制代码

2.3.3 总结

根据定义和代码,可以看出工厂模式的主要作用是根据不同的参数,创建出实现了相同 interface 的不同的对象,所以属于创建模式

三.策略模式

3.1 核心思想

策略模式是一种行为模式,它允许您定义一系列算法,将它们中的每一个放入一个单独的类中,并使它们的对象可互换。

3.2 实现框架


1.context 保持到具体的策略和进行通信与该对象仅通过策略接口的一个参考。

2.strategy 的接口是通用于所有具体的战略。它声明了上下文用来执行策略的方法。

3.concrete strategies 实现了上下文使用的算法的不同变体。

4.每次需要运行算法时,context 都会调用链接策略对象上的执行方法。context 不知道它使用什么类型的策略或算法是如何执行的。

5.client 创建一个 concrete strategy,并把它传递给 contextcontext 公开了一个 setter,它允许客户端在运行时替换与 context 关联的策略。

3.3

Strategy interface

package main
type evictionAlgo interface { evict(c *cache)}
复制代码

fifo.go: Concrete strategy

package main
import "fmt"
type lru struct {}
func (l *lru) evict(c *cache) { fmt.Println("Evicting by lru strtegy")}
复制代码


lfu.go: Concrete strategy

package main
import "fmt"
type lfu struct {}
func (l *lfu) evict(c *cache) { fmt.Println("Evicting by lfu strtegy")}
复制代码

cache.go: Context

package main
type cache struct { storage map[string]string evictionAlgo evictionAlgo capacity int maxCapacity int}
func initCache(e evictionAlgo) *cache { storage := make(map[string]string) return &cache{ storage: storage, evictionAlgo: e, capacity: 0, maxCapacity: 2, }}
func (c *cache) setEvictionAlgo(e evictionAlgo) { c.evictionAlgo = e}
func (c *cache) add(key, value string) { if c.capacity == c.maxCapacity { c.evict() } c.capacity++ c.storage[key] = value}
func (c *cache) get(key string) { delete(c.storage, key)}
func (c *cache) evict() { c.evictionAlgo.evict(c) c.capacity--}
复制代码

main.go: Client code

package main
func main() { lfu := &lfu{} cache := initCache(lfu)
cache.add("a", "1") cache.add("b", "2")
cache.add("c", "3")
lru := &lru{} cache.setEvictionAlgo(lru)
cache.add("d", "4")
fifo := &fifo{} cache.setEvictionAlgo(fifo)
cache.add("e", "5")
}
复制代码


四.总结

由上述可知工厂模式策略模式都可以解决代码的 if,else 冗余,只不过解决的方式在两个维度

工厂模式

将对 interface 的不同实现对象的创建汇聚在工厂内,用户可以按情况生产不同的对象,然后使用不同对象去做相同事情,只不过对象各自对该事件的实现方式不一样,核心目标是简化对象的创建,所以是创建模式的一种设计模式

策略模式

提供上下文接口,根据传入的对象,执行统一的行为,不同的对象自身有各自的实现,与工厂模式十分相似,不同点在于策略模式是根据不同的对象去执行统一的行为,这个行为的具体逻辑又由于对象的不同而不同,如都是淘汰行为,但根据传入的对象类型不同执行不同的淘汰逻辑,重点是根据不同对象来执行对象的行为,是行为模式。

参考文档

https://refactoring.guru/design-patterns/strategy

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

https://blog.csdn.net/hello_bravo_/article/details/104978619(笔者之前的博客)

https://blog.csdn.net/hello_bravo_/article/details/104786592(笔者之前的博客)


发布于: 刚刚阅读数: 2
用户头像

en

关注

努力分享对他人有价值的知识 2018.06.14 加入

还未添加个人简介

评论

发布
暂无评论
设计模式--策略模式与工厂模式