go语言设计模式-单例模式与原型模式

想象不到的简单go单例模式与原型模式

  • 简介
    • 单例模式
    • 原型模式

简介

本文主要说一下设计模式之单例模式与原型,后续会有更多的模式和算法以及区块链相关的,如果你是想学习go语言或者是对设计模式或者算法感兴趣亦或是区块链开发工作者,都可以关注一下。(vx公号,csdn:Go语言之美。头条:Go语言之美。更多go语言知识信息等)。
更多go语言内容:github

单例模式

单例模式是我们在项目中经常用到的设计模式,定义:单例对象的类必须保证只有一个实例存在,全局有唯一接口访问。主要有两种方式:

  • 懒汉方式:指全局的单例实例在第一次被使用时构建。缺点:非线程安全。当正在创建时,有其他线程来访问并且当前对象还未创建结束,就会同时创建多个示例,单例类就会有多个实例了。代码:
1 type singleton struct{}
2 var ins *singleton
3 func GetIns() *singleton{
4 if ins == nil {
5   ins = &singleton{}
6 }
7 return ins
8 }
  • 饿汉方式:指全局的单例实例在类装载时构建。缺点:如果实例化复杂时,将会增加耗时。代码:
1 type singleton struct{}
2 var ins *singleton = &singleton{}
3 func GetIns() *singleton{
4   return ins
5 }

我们日常最多用的方法就是懒汉加锁,保证了线程安全同时减少实例化耗时。在go语言中也可以这样做,但是go有更加简单的方式,上代码:

1 type singleton struct{}
2 var ins *singleton
3 var once sync.Once
4 func GetIns() *singleton {
5   once.Do(func(){
6    ins = &singleton{}
7   })
8   return ins
9 }

这种方式实质上也是懒汉加锁,只不过去掉了对 ins 是否为空的判断,神奇的地方就是 once.Do 方法。对于从全局的角度只需要运行一次的代码,比如全局初化操始作,go语言提供了一个Once类型来保证全局的唯一性操作。当有多线程(go中叫做goroutine)并发时,也可以保证只执行一次,其实内部还是加锁了。从这里就可以看出go语言的简单性,作为程序员2019年最想学习的语言不是没有道理的。

原型模式

接下来我们聊聊原型模式。定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。说白了,就是根据已经存在的实例,复制一份,然后修改成自己想要的(个人理解)。闲话少叙,上代码:

1 package main
2 import (
3   "fmt"
4 )
5 type PersonalInfo struct {
6   name string
7   sex string
8   age string
9 }
10 type WorkExperience struct {
11   timeArea string
12   company string
13 }
14 type Resume struct {
15   PersonalInfo
16   WorkExperience
17 }
18 func (this *Resume) SetPersonalInfo(name string, sex string, age string) {
19   this.name = name
20   this.sex = sex
21   this.age = age
22 }
23 func (this *Resume) SetWorkExperience(timeArea string, company string) {
24   this.timeArea = timeArea
25   this.company = company
26 }
27 func (this *Resume) Display() {
28   fmt.Println(this.name, this.sex, this.age)
29   fmt.Println("工作经历:", this.timeArea, this.company)
30 }
31 func (this *Resume) Clone() *Resume {
32   resume := *this
33   return &resume
34 }
35 func main() {
36   r1 := &Resume{}
37   r1.SetPersonalInfo("大鸟", "男", "29")
38   r1.SetWorkExperience("1998-2000", "xx公司")
39   r2 := r1.Clone()
40   r2.SetWorkExperience("2001-2006", "yy公司")
41   r3 := r1.Clone()
42   r3.SetPersonalInfo("大鸟", "男", "24")
43   r1.Display()
44   r2.Display()
45   r3.Display()
46 }

简历是我们最常用的原型模式的例子。不知道大家有没有过这样的经历,自己不知道怎么写简历,把别人的简历拷贝一份,然后改上自己的信息与工作经验等。这就是典型的原型模式,我把已经存在的实例复制一份,然后改成自己想要的,这样就不需要重复构造相同的东西。原型模式还有一个深复制和浅复制的问题,就是我们的 Resume 结构体继承了 PersonalInfo 和 WorkExperience,当我们 clone 一个新的 resume 之后,要注意里面里面引用的其他结构体是否也被复制,不然就会存在两个 resume 使用同一个个人信息。目前我在用的时候没有发绳这个问题,都是深度复制过来(如果大家以后发现这个问题请立即联系作者)。

今天先说这两个模式,后续会有更多的模式和算法以及区块链相关的,感兴趣的可以关注一下(vx公号,csdn:Go语言之美。头条:Go语言之美。更多go语言知识信息等:github)。

你可能感兴趣的:(go,go,设计模式,单例模式,原型模式)