百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Go设计模式(1)-语法(gof常用设计模式)

ccwgpt 2024-10-10 04:51 32 浏览 0 评论

简介

最近思考了一下这几年写的业务,都是用面向过程思路来实现。之所以用面向过程

一是因为大家都这么写,很少去思考是否有更好的实现

二是业务简单,使用面向过程编程可以很方便的实现

三是业务需要快速上线,面向过程的方法更快更直接

但是弊端也很明显,随着业务不断的积累,项目改动起来比较困难,需要不断梳理前人是怎么写的、有什么影响,测试需要做大量的测试,确保功能是正常的。有时候即使是相似或者迭代性的需求也无法保证快速上线。而且即使耗费了大量的人力,也很难保证没有遗漏。这时候就想起面向对象的好。

四大特性

面向对象编程有四大特性

  1. 封装特性封装也叫作信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式来访问内部信息或者数据。它需要编程语言提供权限访问控制语法来支持,例如Java中的private、protected、public关键字。封装特性存在的意义,一方面是保护数据不被随意修改,提高代码的可维护性;另一方面是仅暴露有限的必要接口,提高类的易用性。
  2. 抽象特性封装主要讲如何隐藏信息、保护数据,那抽象就是讲如何隐藏方法的具体实现,让使用者只需要关心方法提供了哪些功能,不需要知道这些功能是如何实现的。抽象可以通过接口类或者抽象类来实现,但也并不需要特殊的语法机制来支持。抽象存在的意义,一方面是提高代码的可扩展性、维护性,修改实现不需要改变定义,减少代码的改动范围;另一方面,它也是处理复杂系统的有效手段,能有效地过滤掉不必要关注的信息。
  3. 继承特性继承是用来表示类之间的is-a关系,分为两种模式:单继承和多继承。单继承表示一个子类只继承一个父类,多继承表示一个子类可以继承多个父类。为了实现继承这个特性,编程语言需要提供特殊的语法机制来支持。继承主要是用来解决代码复用的问题。
  4. 多态特性多态是指子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。多态这种特性也需要编程语言提供特殊的语法机制来实现,比如继承、接口类、duck-typing。多态可以提高代码的扩展性和复用性,是很多设计模式、设计原则、编程技巧的代码实现基础。

实现

想要用面向对象编程来实现业务逻辑,必然需要掌握的是如何使用这门语言实现四大特性。在掌握了这份知识的基础上,才有可能灵活的使用设计模式,设计出好的架构。今后学习新的语言的时候,对于面向对象的实现,需要成为关注点之一。看下面的内容需要掌握基本的Go语言知识。

封装

Go中封装的实现方法为使用结构体,并给结构体添加相应的方法。

一般的实现步骤如下:

  1. 将结构体、字段的首字母小写;
  2. 给结构体所在的包提供一个工厂模式的函数,首字母大写,类似一个构造函数;
  3. 提供一个首字母大写的Set方法(类似其它语言的public),用于对属性判断并赋值;
  4. 提供一个首字母大写的Get方法(类似其它语言的public),用于获取属性的值。

举例:对于员工,不能随便查看年龄,工资等隐私,并对输入的年龄进行合理的验证。代码结构如下

package model

import "fmt"

type person struct {
   Name string
   age  int //其它包不能直接访问..
   sal  float64
}

//写一个工厂模式的函数,相当于构造函数
func NewPerson(name string) *person {
   return &person{
      Name: name,
   }
}

//为了访问age 和 sal 我们编写一对SetXxx的方法和GetXxx的方法
func (p *person) SetAge(age int) {
   if age > 0 && age < 150 {
      p.age = age
   } else {
      fmt.Println("年龄范围不正确..")
      //给程序员给一个默认值
   }
}
func (p *person) GetAge() int {
   return p.age
}

func (p *person) SetSal(sal float64) {
   if sal >= 3000 && sal <= 30000 {
      p.sal = sal
   } else {
      fmt.Println("薪水范围不正确..")
   }
}

func (p *person) GetSal() float64 {
   return p.sal
}

关于这个代码,有两点需要说明

1.关于大小写

  • 小写字母开头的函数只在本包内可见,大写字母开头的函数才能被其他包使用。这个规则也适用于类型和变量的可见性。
  • 大小写影响了可见性,大写字母开头等同于public,小写字母开头等同于private,这种做法不仅免除了public、private关键字,更重要的是统一了命名风格。

2.结构体方法参数

  • 如果要求对象必须以指针传递,这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。
  • 只有在你需要修改对象的时候,才必须用指针。

继承

Go语言根本就不支持面向对象思想中的继承语法。

从另一个维度而言,Go语言也提供了继承,但是采用了组合的文法,所以我们将其称为匿名组合。

举例:

package main

import "fmt"

type Base struct {
   Name string
}

func (b *Base) SetName(name string) {
   b.Name = name
}

func (b *Base) GetName() string {
   return b.Name
}

// 组合,实现继承
type Child struct {
   base Base // 这里保存的是Base类型
}

// 重写GetName方法
func (c *Child) GetName() string {
   c.base.SetName("modify...")
   return c.base.GetName()
}

// 实现继承,但需要外部提供一个Base的实例
type Child2 struct {
   base *Base // 这里是指针
}

//
type Child3 struct {
   Base
}

type Child4 struct {
   *Base
}

func main() {
   c := new(Child)
   c.base.SetName("world")
   fmt.Println(c.GetName())

   c2 := new(Child2)
   c2.base = new(Base) // 因为Child2里面的Base是指针类型,所以必须提供一个Base的实例
   c2.base.SetName("ccc")
   fmt.Println(c2.base.GetName())

   c3 := new(Child3)
   c3.SetName("1111")
   fmt.Println(c3.GetName())

   c4 := new(Child4)
   c4.Base = new(Base)
   c4.SetName("2222")
   fmt.Println(c4.GetName())
}

关于这段代码,有几点需要说明

  1. 可以使用匿名组合和非匿名组合,如果使用非匿名组合,则调用的时候需要显示指定变量名称。如果使用匿名组合,则无需显示指定变量名称,当然也可以显示调用,如c3.Base.Name。
  2. 在Go语言中,还可以以指针方式从一个类型“派生”:如Child4,这段Go代码仍然有“派生”的效果,只是Child4创建实例的时候,需要外部提供一个Base类实例的指针。
  3. 在“派生类”Child3没有改写“基类”Base的成员方法时,相应的方法就被“继承”,例如在上面的例子中,调用c3.GetName()和调用c3.Base.GetName()效果一致。在“派生类”Child改写“基类”Base的成员方法,c.GetName()会调用派生类的方法,如果想调用基类的方法,可以显示调用。
  4. 如果“派生类”和“基类”有相同的变量名Name,所有的派生类的Name成员的访问都只会访问到最外层的那个Name变量,基类的Name变量相当于被覆盖了,可以用显示引用。

多态

在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口。如果类实现了接口,便可将对象实例赋值给接口。

举例:

package main

import "fmt"

type Money interface {
   show() string
}

type OldMoney struct {
}

func (oldMoney *OldMoney) show() string {
   return "I am old money"
}

type NewMoney struct {
}

func (newMoney *NewMoney) show() string {
   return "I am new money"
}

func PrintMoney(l []Money) {
   for _, item := range l {
      fmt.Println(item.show())
   }
}

func main() {
   moneyList := []Money{new(OldMoney), new(NewMoney), new(OldMoney)}
   PrintMoney(moneyList)
}

关于这段代码,有几点需要说明:

  1. 接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A。
  2. Go语言可以根据下面的函数:func (oldMoney OldMoney) show() string自动生成一个新的show()方法:func (oldMoney *OldMoney) show() string,所以赋值时使用引用还是对象,需要考虑函数参数的类型。

结论

简单梳理了一下Go语言的特性,使用Go做面向对象编程及其简单。后面会用Go实现23设计模式。

资料

  1. Go语言中 封装的理解和实现细节 (Golang经典编程案例)https://blog.csdn.net/cui_yonghua/article/details/94346590
  2. golang继承与接口https://www.cnblogs.com/ExMan/p/11773843.html
  3. golang继承https://studygolang.com/articles/12114
  4. Golang组合和匿名的区别https://blog.csdn.net/wangkai_123456/article/details/107894993
  5. 二十七.golang的多态

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

技术

  1. MySQL开发规范
  2. HTTPS配置实战
  3. Go通道实现原理
  4. Go定时器实现原理
  5. HTTPS连接过程
  6. 限流实现2
  7. 秒杀系统
  8. 分布式系统与一致性协议
  9. 微服务之服务框架和注册中心
  10. Beego框架使用
  11. 浅谈微服务
  12. TCP性能优化
  13. 限流实现1
  14. Redis实现分布式锁
  15. Golang源码BUG追查
  16. 事务原子性、一致性、持久性的实现原理
  17. CDN请求过程详解
  18. 常用缓存技巧
  19. 如何高效对接第三方支付
  20. Gin框架简洁版
  21. InnoDB锁与事务简析
  22. 算法总结

读书笔记

  1. 原则
  2. 资治通鉴
  3. 敏捷革命
  4. 如何锻炼自己的记忆力
  5. 简单的逻辑学-读后感
  6. 热风-读后感
  7. 论语-读后感
  8. 孙子兵法-读后感

思考

  1. 服务端团队假期值班方案
  2. 项目流程管理
  3. 对项目管理的一些看法
  4. 对产品经理的一些思考
  5. 关于程序员职业发展的思考
  6. 关于代码review的思考
  7. Markdown编辑器推荐-typora

相关推荐

团队管理“布阵术”:3招让你的团队战斗力爆表!

为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...

知情人士回应字节大模型团队架构调整

【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...

豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍

强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...

创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)

创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...

消息称吴永辉入职后引发字节大模型团队架构大调整

2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...

31页组织效能提升模型,经营管理团队搭建框架与权责定位

分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...

异形柱结构(异形柱结构技术规程)

下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...

职场干货:金字塔原理(金字塔原理实战篇)

金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...

底部剪力法(底部剪力法的基本原理)

某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...

结构等效重力荷载代表值(等效重力荷载系数)

某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...

体系结构已成昭告后世善莫大焉(体系构架是什么意思)

实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...

框架柱抗震构造要求(框架柱抗震设计)

某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...

梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)

某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...

死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?

活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...

不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么

最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...

取消回复欢迎 发表评论: