首页 > 其他分享 >12 享元模式 -- go语言设计模式

12 享元模式 -- go语言设计模式

时间:2023-08-13 17:32:20浏览次数:40  
标签:享元 12 return name object flyweight func 设计模式 pool

享元模式(Flyweight Pattern)是一种结构型设计模式,用于有效地支持大量细粒度对象的共享。享元模式通过共享对象的方式来减少内存使用和提高性能。

享元模式的实现代码

package main
 
import (
   "fmt"
   "sync"
)
 
/*
业务场景描述:
- 租车场景,客户像车行租车,如果车行有车直接租给客户,没有则从车行的其他分部调车分配
场景角色:
- 1.抽象享元,接口,实现产品具有属性
- 2.具体享元,类,实现抽象享元
- 3.享元工厂,控制和管理享元
- 4.客户端,请求获取产品
 
 */
 
// 1.抽象享元-便于扩展
type iFlyweight interface {
   drive()
}
 
// 2.具体享元
type flyweight struct {
   name string
}
 
func NewFlyweight(name string) *flyweight {
   return &flyweight{
      name: name,
   }
}
 
func (r *flyweight) drive()  {
   fmt.Printf("the car [%s] is driving on the road.\n", r.name)
}
 
// 3.享元工厂
type flyweightFactory struct {
   pool map[string]*flyweight
}
 
func NewFlyweightFactory() *flyweightFactory {
   return &flyweightFactory{
      pool: make(map[string]*flyweight),
   }
}
 
func (r *flyweightFactory) Get(name string) *flyweight {
   object, ok := r.pool[name]
   if !ok {
      object = r.schedule(name)
      r.pool[name] = object
   }
 
   return object
}
 
// 相当于新建对象
func (r *flyweightFactory) schedule(name string) *flyweight {
   fmt.Printf("车行从其他分部调入: [%s]\n", name)
   return &flyweight{name}
}
 
// 用完之后的还车
func (r *flyweightFactory ) Put(object *flyweight) error {
   r.pool[object.name] = object
   return nil
}
 
// sync.pool 实现,封装更好,直接get、put即可
type flyweightFactoryV2 struct {
   pool sync.Pool
}
 
func NewFlyweightFactoryV2() *flyweightFactoryV2 {
   factory := &flyweightFactoryV2{}
   factory.pool.New = func() any {
      return new(flyweight)
   }
 
   return factory
}
 
func (r *flyweightFactoryV2) Get(name string) *flyweight {
   // 使用时需要断言
   object := r.pool.Get().(*flyweight)
 
   return r.warp(name, object)
}
 
func (r *flyweightFactoryV2) warp(name string, fly *flyweight) *flyweight {
   fmt.Printf("正在租出一辆车: [%s]\n", name)
   fly.name = name
   return fly
}
 
// 用完之后的还车
func (r *flyweightFactoryV2) Put(object *flyweight) error {
   r.pool.Put(object)
   return nil
}
 
// 4.客户端
func main()  {
   // map实现共享池
   fac := NewFlyweightFactory()
   // 获取对象
   car := fac.Get("BMW")
   // 使用对象
   car.drive()
   // 用完还车
   _ = fac.Put(car)
 
   // 再次租车
   car1 := fac.Get("BMW")
 
   // 租其他车
   car2 := fac.Get("Benz")
 
   // 直接还车
   fac.Put(car1)
   fac.Put(car2)
 
   /* result:
   车行从其他分部调入: [BMW]
   the car [BMW] can driving on the road.
   车行从其他分部调入: [Benz]
    */
 
   // sync.Pool实现共享池
   facV2 := NewFlyweightFactoryV2()
   // rent
   car3 := facV2.Get("RR")
 
   // use
   car3.drive()
 
   // return car
   facV2.Put(car3)
}

终端输出

1.png

享元模式的代码拆分

1.项目的准备工作

找到 go 的 GOPATH

$ go env		//可以查看 GOPATH

在 GOPATH 目录下创建3个文件夹

1.bin文件夹		-- 存放编译后的二进制文件

2.pkg文件夹		-- 存放编译后的库文件

3.src文件夹		-- 存放源码文件

2.创建文件夹

//	-- 在项目文件夹 flyweight_case 里创建新文件夹

//	flyweight	-- 存放装饰者的全部文件

2.png

3.接口文件 -- flyweight文件夹

文件1 -- iflyweight.go

package flyweight

// 抽象享元-便于扩展
type iFlyweight interface {
   Drive()
}

4.结构体文件 -- flyweight文件夹

文件1 -- flyweight.go

package flyweight

import "fmt"

// 具体享元
type flyweight struct {
   name string
}
// 创建享元
func NewFlyweight(name string) *flyweight {
   return &flyweight{
      name: name,
   }
}
// 汽车在行驶
func (r *flyweight) Drive()  {
   fmt.Printf("the car [%s] is driving on the road.\n", r.name)
}

文件2 -- fwfactory.go

package flyweight

import "fmt"

// 享元工厂
type flyweightFactory struct {
   pool map[string]*flyweight
}
// 新建享元工厂
func NewFlyweightFactory() *flyweightFactory {
   return &flyweightFactory{
      pool: make(map[string]*flyweight),
   }
}
// 根据名字获取汽车
func (r *flyweightFactory) Get(name string) *flyweight {
   object, ok := r.pool[name]
   if !ok { //如果该汽车不存在,就从其他分部调入
      object = r.schedule(name)
      r.pool[name] = object
   }
 
   return object
}
 
// 相当于新建对象
func (r *flyweightFactory) schedule(name string) *flyweight {
   fmt.Printf("车行从其他分部调入: [%s]\n", name)
   return &flyweight{name}
}
 
// 用完之后的还车
func (r *flyweightFactory ) Put(object *flyweight) error {
   r.pool[object.name] = object
   return nil
}

文件3 -- fwfactoryv2.go

package flyweight

import (
	"fmt"
	"sync"
)

// sync.pool 实现,封装更好,直接get、put即可
type flyweightFactoryV2 struct {
   pool sync.Pool
}
 
func NewFlyweightFactoryV2() *flyweightFactoryV2 {
   factory := &flyweightFactoryV2{}
   factory.pool.New = func() any { // any 为空接口
      return new(flyweight)
   }
 
   return factory
}
// 租车
func (r *flyweightFactoryV2) Get(name string) *flyweight {
   // 使用时需要断言
   object := r.pool.Get().(*flyweight)
 	// 租车并且返回该车
   return r.warp(name, object) 
}
 
func (r *flyweightFactoryV2) warp(name string, fly *flyweight) *flyweight {
   fmt.Printf("正在租出一辆车: [%s]\n", name)
   fly.name = name
   return fly
}
 
// 用完之后的还车
func (r *flyweightFactoryV2) Put(object *flyweight) error {
   r.pool.Put(object)
   return nil
}

5.主文件 -- main.go 在项目文件夹

package main

import (
	"design/flyweight_case/flyweight"
)

// 客户端
func main()  {
   // map实现共享池
   fac := flyweight.NewFlyweightFactory()
   // 获取对象
   car := fac.Get("BMW")
   // 使用对象
   car.Drive()
   // 用完还车
   _ = fac.Put(car)
 
   // 再次租车
   car1 := fac.Get("BMW")
 
   // 租其他车
   car2 := fac.Get("Benz")
 
   // 直接还车
   fac.Put(car1)
   fac.Put(car2)
 
   /* result:
   车行从其他分部调入: [BMW]
   the car [BMW] can driving on the road.
   车行从其他分部调入: [Benz]
    */
 
   // sync.Pool实现共享池
   facV2 := flyweight.NewFlyweightFactoryV2()
   // rent
   car3 := facV2.Get("RR")
 
   // use
   car3.Drive()
 
   // return car
   facV2.Put(car3)
}

终端输出

3.png

6.全部文件图

4.png

标签:享元,12,return,name,object,flyweight,func,设计模式,pool
From: https://blog.51cto.com/u_14483476/7068271

相关文章

  • 【Java】美团8.12笔试复盘
    5道编程题2小时如果您看到哪里有问题,万望评论区指正,在此谢过!!!第一题:数组遍历importjava.util.Scanner;publicclassNextNumbers{/*题目:给你一个排列和两个数问你:这两个数在排列里是不是相邻输入:第一行:n代表排列中数的个数第二行:a1--an......
  • 【专题】中国职业教育发展报告(2012-2022年)报告PDF合集分享(附原数据表)
    学习能力是将知识资源转化为知识资本的能力。它包括对所学内容的兴趣和热情,有助于更深入理解和掌握知识,提高个人的认知和思维能力。阅读原文,获取专题报告合集全文,解锁文末158份学习教育行业相关报告。教育和娱乐支出越来越成为家庭消费的重要组成部分。这包括对18岁以下儿童的素质......
  • 8.12 2014 年 JOI 圆满结束
    稻草人按\(x\)排序,可以将问题转化为寻找点对\((i,j)\),使得\(y[i]<y[j]\)且对于所有\(i<k<j\),都不满足\(y[i]<y[k]<y[j]\)。点对问题,考虑\(CDQ\)分治。容易发现最终对点\(i\)产生贡献的\(j\)的\(y[j]\)单调递减,可以使用单调栈维护。单调栈内即是右边所有可以满......
  • 8-12|go语言之输入
    在Go语言中,输入主要是通过标准库中的包来实现的。常用的包有`fmt`和`bufio`。以下是一些基本的Go输入方法:1.**使用`fmt.Scan()`和相关函数**:    `fmt.Scan()`,`fmt.Scanln()`,和`fmt.Scanf()`是用于从标准输入读取值的常用方法。    ```go  ......
  • 8月5号到8月12号。假期周总结
    8月5号到8月12号。周日我看了一下Python的课程二进制编码,标识符保留四变量的定义使用,还有给变量赋值数据的类型。周一我学习了Python的输入输出运算符的使用方法,有运算符的优先级。还有分支结构,单分支结构,双分支结构,多分支结构,嵌套的分支结构。我还学习了一下条件表达式。周二我......
  • 做题记录:P3121 [USACO15FEB] Censoring G
    题目传送门:clickhere题意简化:给定一个文本串,和n个匹配串,删掉文本串中的匹配串求最后的字符串做这题之前应该先做简化版:eazymode上面这题用kmp+栈就能过以前如果用的是\(erase\)函数是错解,字符串的\(erase\)时间复杂度是常数级别的看到这道题后非常的高兴,直接打了个爆力跳......
  • kylin v10 安装 Oracle 19c/12c遇到问题汇总
    适用范围麒麟_v10_sp1_20200711Oracle19c/12c银河麒麟V10sp1内核版本redhat8.6内核版本遇到问题19c问题1PRVG-0282:failedtoretrievetheoperatingsystemdistributionIDOracle是不支持在银河麒麟上安装的,但由于银河麒麟也属于redhat系,我们就能伪装自己是redhat系统,从......
  • 2023.8.12
    又是一周的结束,浅浅做个总结,这周主要有三天没有在家,没带电脑,出去玩了几天,也就没学多少,主要是有时间的时候在手机上做一下pta的题目,简单看了一下那个考试题目,感觉有点困难,看来还没完全学会,下周找一些资源视频什么的看一看,这周总结大概就是这样,下周继续努力。......
  • 2023.8.12 普及月赛记录
    比赛传送门按照往常的经验,A和B应该都问题不大,而且我不注重抢什么首杀,于是这次改变策略:C\(\rightarrow\)D\(\rightarrow\)B\(\rightarrow\)A。先看C。题目:queue。嗯~不错,原来是大模拟,出题人非常的CCF。看完感觉就是简单的维护几个队列的模拟,感觉难度不大。然后感觉自......
  • 暑期熔炉8月12
    运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。非运行时异常是指RuntimeExcept......