摘要:本文咱们首要介绍结构型办法中的署理办法、装修办法、外观办法和享元办法。
本文指针万用表的使用办法同享自华为云社区《快来,这里有2数据库规划3种规划办法的Go言数据库课程规划语完毕(三数据库规划)》,原文作者:元闰子 。
规划办法(Des架构师和程序员的差异ign Pa指针表tte指针c言语rn)是一套被重复运用、多数人知晓的、经过分类编意图、代码规划经历的总结,运用规划办法是为了可重用代码、让代码更简数据库体系的中心是略被他数据库课程规划人理解而且确保代码可靠性。本文将介绍几种结构型办法:署理办法、装修办法、外观办法和享元办法。
署理办法(Proxy P架构师薪酬一月多少attern)
简介
署理方接口是什么式为一个方针供给一种署理以操控对该方针的拜访,它是一个运用率十分高的缓存是什么意思规划办法,即便在现实生活中,也是很常见,比方演唱会门票黄牛。假定你需求看一场演唱会,可是官网上门票现已售罄,所以数据库体系概论第五版课后答案就当天到现场经过黄指针数学牛高价买了一张。在这个比方中,黄数据库体系牛就相当于演唱会门票的署理,在正式途径无法购买门票的状况下,你经过署理完毕了该方针。
从演唱会门票的比方咱们也能够看出,运用署理办法的关键在于当 Client 不方便直接拜访一个方针时,供给一个数据库体系署理方针操控该方针的拜访。Client 实际上拜访的是署理方针,署理方针会将 Client 的请求转给本体方针去处理。
在程序规划中,署理办法也分为好几种:
1、长途署理(remote proxy),长途署理适用于供给服务的方针处在长途的机器上,经过普通的函数调用无法运用服务,需求经过长途署理来完毕。因为并不能直接拜访本体方针,悉数长途署理方针一般不会直接持有本体缓存的视频怎样保存到本地方针的引证,而是持有远端机器的地址,经过网络协议去拜访本体方针。
2、虚拟署理(virtual proxy),在程序规划中常常会有一些重量级的服务方针,假设一贯持有该方针实例指针会十分耗费体系资源,这时能够经过虚拟署理来对该方针进行指针的拼音推延初始化。
3、维护署理(protection prox缓存是什么意思y),维护署理用于操控对本架构师需求掌握哪些知识体方针的拜访,常用于需求给 Client 的拜访加上权限验证的场景。
4、缓存署理(cache proxy),缓存署理首要在 Client 与接口卡本体方针之间加上一层缓存,用于加速本体方针的拜访,指针数组和数组指针的差异常见于联接数据库的场景。
5、智能引证(smart refe架构师和程序员的差异rence),智能引证为本体方针的拜访供给了额定的动作,常见的完毕为 C++中的智能指针接口卡,为方针的拜访供给了计数功用,当拜访方针的计数为 0 时毁掉该方针缓存视频怎样转入本地视频。
这几种署理都是相同的完毕原理,下面咱们将介绍长途署理的 G指针数组o 言语完毕。
Go 完毕
考虑要将音讯处理体系输出到数据存储到一个数据库中,数据库的接口如下:
package db
...
// Key-Value数据库接口接口卡
type KvDb interface {
// 存储数据
// 其间reply为操作作用,存储成功为true,否则为false
// 当联接数据库失利时回来error,成功则回来nil
Save(record Record, reply *bool) error
// 根据key获取value,其间value经过函数参数中指针类型回来
// 当联接数据库失利时回来error,成功则回来nil
Get(key string, value *string) error
}
type Record struct {
Key string
Value string
}
数据库是一个 Key-Va指针数组和数组指针的差异lue 数据库,运用 map 存储数据,下面为数据库的服务端完毕,db.Server 完毕了 db.KvDb 接口:
package db
...
// 数据库服务端结接口类型束
type Server struct {
// 选用map存储key-value数据
data缓存视频 map[string]string
}
func (s *Server) Sav数据库课程规划e(reco架构师薪酬一月多少rd Reco接口的作用rd, reply指针数组和数组指针的差异 *bool) error {
if架构是什么意思 s.data == nil{
s.data = make(map[st指针ring]strin指针表g)
}
s.data[record.K指针万用表的使用办法ey] = record指针.Value
*reply = true
return nil
}
func (s *Server) Get(key string, reply *string) e数据库规划rror {
val, ok := s.data[key]
if !ok {
*reply = ""
return errors.New("Db h缓存视频兼并as no key " + key)
}
*reply = val
return nil
}
音讯处理体系和数据库并不在同一台机器上,因而音讯处指针式万用表图片理体系不能直接调用 db.Serve架构师r 的办法进行数据存储,像这种服务供给者和服务运用者不在同一机器上的场景,运用长途署理再适合不过了。
长途署理中,最常见的一种完毕是长途过程调用(Remote Procedure Call,简称 RPC),架构规划它答应客户端运用能够像调用本当地针相同直接调用另一台不同的机器上服务端运用的办法数据库体系。在 Go 言语领域,除了大名鼎鼎的 gRPC,Go 标准库 net/rpc 包接口类型里也供给了 RPC 的完毕。下面,咱们经过 net/rpc 对外供给数据库服务端的才干:
package db
...
// 发起数据库,对外供给RPC指针数学接口进行数据库的拜访
func Start() {
rpcServer := rpc.NewServer()
server := &Server{data: make(map[string]string)}
// 将数据库接口注册到RPC服务器上
if err := rpcServer.Registe数据库规划r(server); err != nil {
fmt.Printf("Register Server to rpc failed, error: %v", err)
return
}
l, err := net.Listen("tcp", "127.0.0.1:1234")
if err != nil {
fmt.Printf("Listen tcp failed, error: %v", err)
return
}
go rpcServer.Accept(l)
time.Sleep(1 * time.Second)
fmt.Println("Rpc server start success.")
}
到目前为止,咱们现已为数据库供给了对外拜访的办法。现在,咱们需求一个长途署理来联接数据库服务端,并进行相关的数据库操作。对接口crc过错计数音讯处理体系而言,它不需求,也不应该知道长途署理与数据库服务端交互的底层细节,这样能够减轻体系之间的耦合。因而,长途署理需求完毕 db.KvDb:
package db
...
// 数据库服务端长途署理架构图,完毕db.KvDb接口
type Client struct {
// RPC接口和抽象类的差异客户端
cli *rpc.Client
}
func (c *Client) Save(record Rec架构ord, reply *bool) error {
var ret bo接口ol
// 经过RPC调用服务数据库端数据库的接口
err := c.cli.Call("Ser缓存的视频怎样保存到本地ver.Save", reco数据库体系概论第五版课后答案rd, &ret)
i接口英文f err != nil {
fmt.P指针万用表的读法rintf("Call db Server.Save rpc failed, error: %v", err)
*reply = false
return err
}
*reply = ret
return nil
}
func (c *Client)数据库管理体系 Get(key string, reply *string) error {
var ret string
// 经过RPC调用服务端的接口
err := c.cli.Call("Server.Get", key, &ret)
if err != nil {
fmt.Pri数据库原理及使用ntf("Call db Se数据库体系概论第五版课后答案rver.Get rpc failed, error: %v", err)
*reply = ""
return err
}
*reply = ret
return nil
}
// 工厂办法,回来长途署理实例
func CreateClient() *Client {
rpcCli, err := rpc.Dial("tcp", "127.0.0.1:1234")
if err != nil {
fmt.Printf("接口类型Create rpc client failed, er数据库体系的中心是ror: %v.", err)
return nil
}
return &Client{cli: rpcCli}
}
作为长途署理的 db.Client接口测验 并没架构图有直接持数据库体系工程师有 db.Server 的引证,而是持有了它的 ip:port,经过 RPC 客户端调用了它的办法。
接指针式万用表图片下来,咱们需求为音讯处理体系完毕一个新的 Output 插件 DbOutput,调用 db.Client 长途署理,将音讯存储到数据库上。
在《运架构图用什么软件做用 Go 完毕 GoF 的 23 种规划办法(二)》中咱们为 Plugin 引进生命周期的三个办法 Start、Stop、Status 之后,每新增一个新的插件,都需求完毕这三个办法。可是大多数插件的这三个办法的缓存文件在哪里逻辑根本一起,因而导致了必定程度的代码冗余。关于重复代码问题,有什么好的处理办法呢?组合办法!
下面,咱们运用组合方数据库式将这个办法提取成一个新的方针 LifeCyc架构师le,这样数据库课程规划新增一个插件时,只需将 LifeCycle 作为匿名成员(嵌入组合),就能处理冗余代码问题了。
package plugin
...
type LifeCycle str缓存视频怎样转入相册uct {
name string
status Status
}
func (l *LifeCycle)接口的作用 Start() {
l.status = Started
fmt.Printf("%s plugin started.n", l.架构师name)
}
func (l *LifeCycle) Stop() {
l.status = Stopped
fmt.Printf("%指针万用表的读法s plugin stopped.n", l.name)
}
func (l *LifeC架构图用什么软件做ycle) Status() Sta指针万用表的读法tu架构师和程序员的差异s {
return l.status
}
数据库原理及使用DbOutput 的完毕如下,它持有一个长途署理,经过后者将音讯存储到远端的数据库中。
package plugin
...
type D指针数组和数组指针的差异bOut接口是什么put struct {
LifeCycle
// 操架构师薪酬一月多少作数据库的长途署理
proxy db.KvDb
}
func (d *DbOutput) Send(msg *msg.Message) {
if d.sta数据库tus != Started {
fmt.Printf("%s is not running, output nothing.n", d.name)
return
}
record :缓存视频兼并app下载= db.Record{
Key: "db",
Value: msg.Body.Items[0],
}
reply := false
err := d.proxy.Save(record, &reply)缓存
if err != nil || !reply {
fmt.Println("Save msg to db server failed.")
}
}
func指针c言语 (d *DbOutput) Init() {
d.proxy = db.CreateClient()
d.name = "db output"
}
查验代码如下:
package test
...
func TestDbOutput(t *testing.T) {
db.Start()
config := pipeline.Config{
Name: "pipeline3",
Input: plugin.Config{
PluginType: plugin.Inp架构图用什么软件做utType,
Name: "hello",
},
Filter: plugin.Config{
PluginType: plugin.FilterType,
Name: "upper",
},
Output: plugin.Config{
PluginType: plugin.OutputType,
Name: "db",
},
}
p := pipeline.Of(config)
p.St指针式万用表art()
p.Exec()
// 验证指针表DbOutput存储的正确性
cli := db.CreateClient()
var val string
err := cli.Get("db", &v指针al)
if err != nil {
t.E缓存视频变成本地视频rrorf("Get架构图用什么软件做 db failed, error: %vn.指针", e缓存rr)
}
if val != "HELLO数据库课程规划 WO数据库体系工程师RLD" {
t.缓存视频怎样转入相册Errorf("e架构图用什么软件做xpect HELLO WORLD, but actual %s.", val)
}
}
// 作业作用
=== RUN TestD缓存是什么意思bOutput
Rpc server start success.
db output plugin starte接口自动化d.
upper filte指针式万用表r plugin started.
hello inpu架构图用word怎样做出来的t plugin started.
Pipeline started.
--缓存的视频怎样保存到本地- PASS: TestDbOutput (1.01s)
PASS
装修办法(D架构图用什么软件做ecorator Pattern)
简介架构是什么意思
在程序规划中,咱们常常需求为方针增加新的行为,许多同学的榜首数据库体系工程师个想法便是扩展本体方针,经过承继的办法抵达意图。可是运用承继不行避免地有如下两个害处:(1)承继时静态的,在编译期间就现已供认,无法在作业时改动方针的行为。(2)子类只能有一个父类,当需求增加的新功用太多时,简略导致类的数量剧增。
关于这种场景,咱们一般会运用装修办法(Decorator Pattern)来处理,它运用组合而非承继的办法,能够动态地为本缓存视频怎样转入相册体方针叠加新的行为缓存视频在手机哪里找。理论上,只需没有束缚,它能够一贯把功用叠加下去。装修办法最经典的运数据库体系用当属 Java 的 I/O 流体系,经过装修办法,运用者能够动态地为原始的输入输出流增加功用,比方按照字符串输入输出,增加缓存等,使得整个 I/O 流体系具有很高的可扩展性和灵活性。
从结构上看,装修办法和署理办法具有很高的相似性,可是两种所偏重的点不相同。前者偏重的是为本体方针增加新的功用,后者偏重的是对本体方针的拜访操控。当然,署理办法中的智能引证在笔者看来就跟装修办法完全相同了。
Go 完毕缓存视频兼并app下载
考虑为音讯处理体系增加这样的一个功用,核算每个音讯输入源别离发生缓存视频在手机哪里找了多少条消架构息,也便是别离核算每个 Input 发生 Mess架构图用什么软件做age 的数量。最简略的办法是在每一个 Input 的 Receive 办法中进行打点核算接口是什么,可是这样会导致核算代码与事务架构规划代码的耦合。假设核算逻辑发生了改动,就会发生霰弹式修改,跟着 Input 类型的增多,架构是什么意思相关代码也会变得越来越难维护。
更好的办法是将核算逻辑放到一个当地,并在每次调用 Input 的 R架构图模板eceive 办法后进行打点核算。而这恰好适合选用装修办法,为 Input(本体方针)供给打点核算功用(新的行为)。我缓存视频变成本地视频们能够规划一个 InputMetricDecorator 作为 I数据库管理体系nput 的装修器,在装修器数据库体系工程师中完毕打点核算的逻辑。
首要,咱们需求规划一个用于核算每个 Input 发生 Message 数量的方针,该方针应该是一个大局仅有的,因而选用单例办法进行了完毕:
package metric
...
// 音讯输入源核算,规划为单例
type input struct {
// 存架构图放核算作用指针式万用表,key为Input类型如hel架构师薪酬一月多少lo、kafka
// v接口和抽象类的差异alue为对应Input的音讯核算
metri指针cs map[string]uint64
//架构图 核算打点时加锁
mu *sync指针表.Mutex
}
// 给接口是什么名称为inputName的Input音讯计数加1
func (i *input) Inc(inputName string) {
i.mu.Lock()
defer i.mu缓存的视频怎样保存到本地.Unlock()
if _, ok := i.metrics[inputName]; !ok {
i.metric数据库体系s[inpu接口文档tName] = 0
}
i.metrics[inputName] = i.metrics[inpu数据库体系工程师tName] + 1
}
/接口是什么/ 输出当前悉数打点的状况
fun指针万用表的读法c (i *input) Show() {
fmt.Pri架构图用word怎样做出来的ntf("Input metric: %vn", i.metrics)
}
// 单例
va指针万用表的读法r inputInstance = &input{
metrics: make(map[string]uin架构图用什么软件做t64),
mu: &am指针万用表的读法p;sync.Mutex{},
}
func Input() *input {
return inputInstance
}
接下来咱们开始完毕 InputMetri接口文档cDecorator,它完毕了 Input 接口,并持有一个指针万用表的读法本体方针 Input。在 InputMetricDecorator 在 Receive 办法中调用本体 Input 的 Receive 办法,并完毕核算动作。
pac指针式万用表kage plugin...type InputMetricDecorator struct { input Input}func (i *InputMetricDecorator) Receive() *msg.Message { //数据库体系工程师 调用本体方针的Receive办法 record := i.in数据库课程规划put.Receive(数据库体系) // 完毕核算逻辑 if inputN接口和抽象类的差异ame, ok := record.Header.It架构师和程序员的差异ems["input"]; ok { metric.Input().Inc数据库体系工程师(inputName) } return record}指针的拼音func (i *InputMetricDecorator接口测验) St接口英文art() { i.inp接口文档ut.Start()}func (i *InputMetricDecorator) Stop()缓存视频在手机哪里找 { i.inp接口自动化ut.Stop()}func (i *InputMetricDecorator) Status() Status { return i.input.Status()}func (i *InputMet数据库技能ricDecorator) Init() { i.input.I指针数组nit()}// 工厂办法, 结缓存文件在哪里束装修器的创立func CreateInputMetricDec缓存视频怎样转入相册orator(input Input) *InputMetr缓存视频怎样转入本地视频icDecorator { return &InputMetricDecorator{input: input}}
终究,咱们在 Pipe数据库体系line 的工厂架构图办法上,为本体 Input 加上 InputMetricDecorator 署理:
package pipeline..指针.// 根据配备创立一个Pipeline实例func Of(conf Confi接口的作用g) *Pipe缓存视频兼并line { p := &Pipeline{} p.in接口卡put = factoryOf(plugin.InputType).Create(conf.Input).(plugin.Input) p.filter = factoryOf(plugin.FilterType).Create(conf.缓存的视频怎样保存到本地Filter).(plugin.Filter) p.outp接口文档ut = f接口是什么actoryOf(p数据库体系的中心是lugi指针的拼音n.OutputType).Create(conf.Output).(plugin.Output) // 为本体Input加上InputMetricDecorator装修接口和抽象类的差异器 p.input = plugin.CreateInputMetricDecorator架构(p.input) return p}
查验代码如下:
package test...func TestInputMetricDecorator(t *testing.T) { p1 := pipeline.Of(pipeline.HelloConfig()) p2 := pipeline.Of(pipeline.KafkaInputConfig()) p1.Start() p2.Start() p1.Exec() p2.Exec() p1.Exec() metric.Input().Show()}// 作业作用=== RUN TestInputMetricDecoratorConsole output plu缓存gin started.Upper filter plugin s架构图tarted.Hello input plugin started.Pipeline started.Console output plugin start接口的作用ed.Upper filter plugin started.Kafka inpu指针万用表的读法t plugin started.Pipeline started.Output: Header:map[content:text input:hello], Body:[HELLO WORLD]Output: Header:map[content:text input:kafka], Body:[I AM MOCK CONSUMER数据库技能.]Output: Header:map[content:text input:hello], Body:[HELLO WORLD]Input metric: map[h缓存视频变成本地视频ello:2 kafka:1]--- PASS: TestInputMetricProxy (0.00s接口crc过错计数)PASS
外观办法(Facade Patte架构rn)
简介
从结构上看,外观办法十分的简略,它首要是为子体系供给了一个更高层次的对外一起接口指针,使得 Client 能够更和睦地运用子体系的功用。图中,SubsystemClass 是子体系中方针的简称,它或许是一个方针缓存视频怎样转入本地视频,也或许是数十个政数据库技能策的调集。外观缓存视频怎样转入相册办法下降了 Client 与 Subsystem 之间的耦合,只需 Facade 不变,接口是什么不管 Subsystem 怎样改动,关于 Client 而言都是无感知的。
外观办法在程序规划顶用的十分多架构师薪酬一月多少,比方咱们在商城上点击购买的按钮数据库技能,关于购买者而言,只看到了购买这一一起的接口,可是关于商城体系而言,其内部则进行了一系列的事务处接口类型理,比方库存检查、订单处理、付出、物流等等。外观办法极大地提升了用接口测验户体会,将用户从杂乱缓存视频的事务流程中解放了出来数据库体系概论第五版课后答案。
外观办法经常运用于分层架构上,一般咱们都会为分层架构中的每一个层级供给一个或多个一起对外的拜访接口,这样就能让各个层级之间的耦合性更低,使得体系的架构更加合理。
Go 完毕
外观办法完毕起来也很简略,仍是考虑前面的音讯处理体系。在 Pipeline 中,每数据库体系一条接口卡音讯会依次经过 Input->Filter->Output 的处理,代码完毕起来便是这样:缓存视频怎样转入相册
p := pipeline.Of(config)message := p.input.Receive()mes架构图sage = p.filter.Process(message)p.output.Send(message)
可是,关于 Pipeline 的运用者而言,他或许并不关心音讯详细的处理流程,他只需知道音讯现现已过 Pipeline 处理即可。因而,咱们需求规划一个简略的对外接口:
package pipe数据库line...func (p *Pipeline) Exec() { msg := p.input.R缓存视频兼并eceive() msg = p.filter.Process(msg) p.output.Send(msg)}
这样,运用者只需简略地调用 Exec 办法,就能完毕一次音讯的处理,查验代码如下:
package test...指针表func TestPipeline数据库技能(t *testing.T) { p := pipeline.Of(pipeline.HelloConfig()) p.Start() // 调用Exec办法完毕一次音讯的处理 p.Exec()}// 作业作用=== RUN TestPip数据库体系工程师elineconsole output plugin started.upper filter plugin started.hello input plugin started.Pi架构图模板peline started.Output: Header:map[content:text input:hello], Bod架构师y:[HELLO WORLD]---缓存视频兼并 PASS: TestPipeline (0.00s)PASS
享元办法(Flyweight架构师薪酬一月多少 Pattern)
简介
在程序规划中,咱们常常会碰到一些很重型的方针,它们一般具有许多的成员缓存视频特色,当体系中充满着许多的这些方针时指针的拼音,体系的内存将会承受巨大的压力。此外,频频的创立这些方针也极大地耗费了体系的 CPU。许多时分,这架构师需求掌握哪些知识些重型方针里,大部分的成员特色都是固定的,这种场景下, 能够运用享元办法进行优化,将其间固定不变的部分规划成同享方针(享元,flyweight),这样就能节省许多的系接口统内存和 CPU。
享元办法摒弃了在每个方针中保存悉数数据的办法,经过同享多个方针所共有的相同状况, 让你能在有限的内存容量中载入更多方针。
当咱们选择对一个重型方针选用享元办法进行优化时,首要需求将该重型方针的特色划分为两类,能够同享的和不能同享的。前者咱们称为缓存视频兼并app下载内部状况(intrinsic state),存储在享元中,不随享元地点上下文指针万用表的读法的改动而改动;后者称为外指针数组部状况(extrinsic state),它的值取决于享元地点的上下文,因而不能同享数据库管理体系。比方,文章 A 和文章 B 都引证了图片架构是什么意思 A,因为文章 A 和文章 B 的文字内容是不相同的,因而文字便是外部状况,不能同享;可是它们所引证的图片 A 是相同的,归于内部状况,因而能够将图片 A 规划为一个享接口英文元
工厂办法架构图用word怎样做出来的一般都会和享元办法结对出现,享元工厂供给了仅有获取享元方针的接口,这样 Client 就感知不到享元是怎样同享的,下降了接口和抽象类的差异模块接口测验的耦合性。享元办法和单例办法有些相似的当地,都是在体系中同架构图用什么软件做享方针,可是单例办法更关心的是方针在体系中只是创立一次,而享元办法更关心的是怎样在多个方针中同享相同的状况。
Go 完毕缓存文件在哪里
假定现在需求规划一个体系指针数学,用于记载 NBA 中的球员信息、球队信息以及竞赛作用。
球队 Team 的数据结构界说如下:
package n数据库体系ba
...
t数据库体系的中心是ype TeamId uint8
con缓存st (
Warrior TeamId = iota数据库课程规划
Laker
)
type Team struct {
Id TeamId // 球队ID
Name string // 球队名称
Players []*Player // 球队中的球员
}
球员 Player 的数据结构界说架构是什么意思如下:
packag架构图用什么软件做e nba
...
type Player struct数据库课程规划 {
Name string // 球员名字
Team TeamId // 球员所属球队ID
}
竞赛作用 Match 的数据结构界说如下:
package nba
...
type Matc架构图用word怎样做出来的h struct {
Date time.Time // 竞赛时间
LocalTeam *Team // 主场球队
VisitorTeam *Team // 客场球队
LocalScore uint8 // 主场球队得分
VisitorScore uint8 // 客场球架构师和程序员的差异队得分
}
func (m *Match) ShowResult() {
fmt.Printf("%s VS %s - %d:%d数据库体系工程师n", m.LocalTeam.架构Name, m.VisitorTeam.Name,
m.LocalScore, m.VisitorSco接口是什么re)
}
NBA 中的一场竞赛由两个球队,主场球队和客场球队,完毕竞赛,对应着代码便是,一个 Match 实例会持有 2 个 Team 实例。目前,NBA 总共由 30 支球队,按照每个赛季每个球队打 82 场常规赛算,一个赛季总共会有 2460 场竞赛,对应地,就会有 4920 个 Te架构图用什么软件做am 实例。可是,NBA数据库课程规划 的 30 支球队是固定的,实际上只需 30 个 Team 实例就能完整地记载一个接口卡赛季的指针数组和数组指针的差异悉数竞赛信息,剩余的 4890 个 Team 实例归于冗接口余的数据。
这种场景下就适合选用享元办法来进行优化,咱们把架构 Team 规划成多个 Match 实缓存文件在哪里例之间的享架构师薪酬一月多少元。享元接口的获取经过享元工厂来完毕,享元工厂 teamFactory 的界说如下,Client 一起运用 teamFactory.TeamOf 办法来获取球队 Team 实例接口类型。其间,每个球队 Team 实例只会创接口的作用建一次,然后增加到球队池中,后续获取都是直接接口卡从池中获取,这样就抵达了同享的意图。
package nba
...
type teamFactory struct {
// 球队池,缓存球队实例
teams map[TeamId]*Team
}
// 根据TeamId获取Team实例,从池中获取,假设池里没有,数据库体系则创立
func (t *teamFactory) TeamOf(id TeamId) *Team {
team, ok := t.teams[id]
if !o架构师需求掌握哪些知识k {
team = createTeam(id)
t.teams[id] = team
}
return team
}
//数据库体系概论第五版课后答案 享元工厂的单例
var f缓存视频actory = &teamFactory{
teams: make(map[TeamId]*缓存是什么意思Team),
}
func Factory() *teamFact指针数组ory {
return factory
}
// 根接口是什么据TeamId创立Team实例,只在TeamOf办法中调用,外部不行见
func createTeam缓存视频变成本地视频(id TeamId) *Team {
switch id {
case Warrior:
w := &Team{
Id: Warrior,
Name: "Go架构lden State Warriors",
}
curry := &Player{
Name: "Stephen架构图模板 Curry",
Team: Warrior,
}
thompson :数据库有哪几种=接口 &Player{
Name: "Klay T缓存视频hompson",
Team: Warrior,
}
w.Players接口英文 = app指针c言语end(w.Players, curry, thompson)
return w
case Laker:
l :=缓存视频在手机哪里找 &Team{
Id: La接口和抽象类的差异ker,
Name: "Los Angeles Lakers",
}
james := &Player指针万用表的读法{
Name: "LeBron James",
Team: Laker缓存视频怎样转入相册,
}
davis := &Player{
Name: "Anthony Davis",
Team: Laker,
}
l.Players = append(l.接口类型Players, james, davis)
return l
default:
fmt.Printf("Get an invalid team id %v.n", id)
return ni数据库l
}
}
查验代码如下:
package test
...
func TestFlyweight(t *testing.T) {
game1 := &nba.接口英文Mat指针万用表的使用办法ch{
Date: time.Date(2020, 1, 10, 9, 30, 0, 0, time.Local),
LocalTeam: nba.Factory().TeamOf(nba.Warrior),
VisitorTeam: nba.Factory().TeamOf(nba.Laker),
Local缓存视频变成本地视频Score: 102,
VisitorScore: 99,
}
game1.ShowResult()
game2 := &接口卡;nba.Match{
Date: time.Date(2020, 1, 12, 9, 30, 0, 0, time.Local),
LocalTeam: nba.Factory().TeamOf(nba.Laker),
VisitorTeam:缓存视频变成本地视频 nba.Factory().指针数组TeamOf(nba.架构是什么意思Warrior),
LocalScore: 110,
VisitorS数据库课程规划core: 118,
}
game2.ShowResult()
// 两个Match的同一个球队应该是同一个实例的
if game1.LocalTeam != game2.VisitorTeam {
t.Errorf("接口类型Warrior team do not use flyweight pattern")
}
}
// 作业作用
=== RUN TestFly数据库原理及使用wei接口crc过错计数ght
Golden State Warriors VS Los Angel接口测验es Lakers - 102:99
Los Angeles Lakers V接口是什么S G架构olden State Warriors - 110:118
--- PASS:缓存是什么意思 TestFlyweight (0.00s)
总结
本文咱们首要介绍了断构型办法中的署理办法、装修办法、外观方架构规划式和享元办法。署理办法为一个方针供给一种署理以操控对该方针的拜访,偏重的是对本体方针的拜访操控;装修办法可接口英文以动态地为本体方针叠加新的行为,偏重的是为本体方针增加新的功缓存视频在手机哪里找用;外观办法为子体系供给了一个更高层次的对外一起接口,偏重的是分层宽和耦;享元办法经过同享方针来下降体系的资源耗费,偏重的是怎样在多个方针中同享相同的状况。
点击重视,榜首时间了解华为云新鲜技能~