前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【建议收藏】如何用Go写出优美的代码-Go的设计模式【原型模式,构造器模式】篇三

【建议收藏】如何用Go写出优美的代码-Go的设计模式【原型模式,构造器模式】篇三

作者头像
公众号-利志分享
发布2022-12-01 16:04:04
3220
发布2022-12-01 16:04:04
举报
文章被收录于专栏:利志分享利志分享利志分享

大家好,我是追麾(hui)。

这是Go的设计模式第三篇,这篇主要分享原型模式,构造器模式。下面我们来看具体模式。

Go的原型模式

业界原型模式定义:通过复制自己达到构造目标对象新实例的对象。

原型模式优缺点

  • 优点
    • 减少了设计中存在大量的相似类或者对象:减少相似类或者对象的重复定义,复制对象的方式提高了某一类型对象的创建性能
    • 克隆对象方便:一个对象很大,初始化对象过程时间长,使用原型模式,隐藏对象的创建细节,性能能大大提高。
  • 缺点
    • 复制实现容易出现深度复制和浅复制问题

由于原型模式会存在浅复制和深度复制的问题,所以我们看下关于深复制和浅复制相关的知识。

浅拷贝:拷贝对象指针,其实是引用地址都一样,所以属于牵一发动全身。

深拷贝:拷贝整个对象,源对象和拷贝对象没有任何关联,也不会受到任何影响。

原型模式的应用场景

  • 对象之间相同或相似,即只是个别的几个属性不同的时候。
  • 创建对象成本较大,例如初始化时间长,占用CPU太多,或者占用网络资源太多等,需要优化资源。
  • 创建一个对象需要繁琐的数据准备或访问权限等,需要提高性能或者提高安全性。

Go原型模式实现方式

package main

import (
 "bytes"
 "encoding/gob"
 "fmt"
)

func main() {
 t1 := ProtoType{
  String: "2",
  Int:    3,
  Slice:  []int{2, 32},
  Map:    map[string]string{"1": "4"},
 }
 t2, err := t1.Clone()
 if err != nil {
  fmt.Println("clone 失败")
  return
 }
 if t2.Slice != nil {
  t2.Slice[0] = 8
 }
 if t2.Map != nil {
  t2.Map["1"] = "5"
 }
 fmt.Println(t1, "\n", t2)
}

// 这个是原型对象
type ProtoType struct {
 String string
 Int    int
 Slice  []int
 Map    map[string]string
}

// 给对象添加Clone方法
func (p *ProtoType) Clone() (*ProtoType, error) {
 // 下面代码是浅拷贝,实际要考虑引用类型的拷贝, 没有使用到引用类型的对象可以使用下面的方式
 // tObj := *p
 var tObj ProtoType
 // 一般实现深拷贝通过gob库实现
 buf := bytes.Buffer{}
 if err := gob.NewEncoder(&buf).Encode(p); err != nil {
  fmt.Println(err)
  return nil, err
 }
 gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(tObj)
 return &tObj, nil
}

Go的构造器模式

业界构造器模式定义:指为构造一个复杂的产品对象进行产品组成元素构建和产品组装的对象。简单点说将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。构造器模式也称建造者模式。

构造器模式优缺点

  • 优点
    • 实现构建和表示相分离:将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。一定程度上提升产品的扩展性。
    • 扩展性好:各个具体的构造者相互独立,有利于系统的解耦。
    • 客户端不必知道产品内部组成的细节:构造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险,这相当于对外屏蔽细节,对内自由调整。
  • 缺点
    • 产品的组成部分必须相同:这限制了其使用范围。
    • 产品内部如果变化比较大:构造者依然需要改动,而且改动比较大。

构造器模式的应用场景

  • 将复杂的对象的构造过程封装独立代码中。

构造器模式由产品、抽象构造者、具体构造者、指挥者等 4 个要素构成,现在我们来分析其基本结构和实现方法。

构造器模式的结构:

  • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体构造者来创建其各个零部件。
  • 抽象构造者(Abstract Builder):它是一个包含创建产品各个子部件的抽象方法的接口。
  • 具体构造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用构造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

构造器模式实现方式

产品角色:武器,抽象构造者是士兵,实体构造器也是士兵,指挥者是主人,在游戏中我们经常会指挥士兵去铸造武器,然后去和其他人对抗。下面我们来写一下这个示例。

package main

import "fmt"

func main() {
 // 一个游戏者
 player := GamePlayers{}
 // 一个士兵
 oneSoldier := OneSoldier{}
 // 游戏者指挥士兵
 player.SetSoldiers(oneSoldier)
 // 游戏者指挥士兵干货
 player.ToDealArms()
}

// 武器对象
type Arms struct {
}

// 士兵抽象构造类
type Soldier interface {
 // 打铁
 ForgeIron() error
 // 冶炼
 Smelting() error
 // 组装
 PackageArms() *Arms
}

// 实体士兵构造者
type OneSoldier struct {
}

// 打铁
func (o *OneSoldier) ForgeIron() error {
 fmt.Println("进行打铁操作~")
 return nil
}

// 冶炼
func (o *OneSoldier) Smelting() error {
 fmt.Println("进行冶炼操作~")
 return nil
}

// 组装
func (o *OneSoldier) PackageArms() *Arms {
 fmt.Println("进行组装生成武器~")
 arms := Arms{}
 return &arms
}

// 游戏玩家 - 指挥一士兵
type GamePlayers struct {
 SoldierList OneSoldier
}

func (g *GamePlayers) SetSoldiers(s OneSoldier) {
 g.SoldierList = s
}

func (g *GamePlayers) GetArms() *Arms {
 return g.SoldierList.PackageArms()
}

// 指挥士兵打铁,冶炼,组装,铸造成兵器
func (g *GamePlayers) ToDealArms() *Arms {
 g.SoldierList.ForgeIron()
 g.SoldierList.Smelting()
 return g.SoldierList.PackageArms()
}

GO设计模式和面试八股文

【建议收藏】如何用Go写出优美的代码-Go的设计模式【单例模式,工厂方法模式】篇一

【建议收藏】如何用Go写出优美的代码-Go的设计模式【简单工厂模式,抽象工厂模式】篇二

【建议收藏】Golang面试干货13问

【建议收藏】Golang面试干货21问

最后

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发,您的支持是我坚持写作最大的动力。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 利志分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Go的原型模式
  • Go的构造器模式
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档