单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点,主要解决一个全局使用的类频繁的创建和销毁,节省内存的开销,避免对资源的多重占用。没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外部怎么实例化的。关键代码构造函数私有化,外部不能随意创建,但是Go语言没这种,private、public。那就用大小写来代替是否对外暴露
大家都要喝水,但是没必要每人家里都打一口井,通常的做法是整个村里打一个井就够了,大家都从这个井里面打水喝。
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
饿汉模式
提前实例化好对象,等待直接调用就行。
优点:写法简单,在类装载时完成实例化,没有加锁,执行效率会提高,避免了线程同步问题。
缺点:类装载时完成实例化,没有达到懒加载的效果,若该实例从未使用,则会造成内存浪费。
func main() {
sing1 := GetInstance()
sing1.SingFunc()
sing2 := GetInstance()
fmt.Printf("sing1:%p\tsing2:%p", sing1, sing2)
}
// 小写代表private,对外暴露GetInstance获取实例
var instance *singleton = new(singleton)
type singleton struct {
}
func GetInstance() *singleton {
return instance
}
func (receiver singleton) SingFunc() {
fmt.Println("饿汉式的方法。。。")
}
/*
饿汉式的方法。。。
sing1:0x660458 sing2:0x660458
懒汉模式
饿汉式可能造成资源浪费,所以就有了懒汉式,先不创建类的对象实例,等需要的时候再创建。
线程不安全:懒加载,没有加锁,所以线程不安全,多线程下不能正常工作。
线程安全:懒加载,能够在多线程中工作,但是加锁效率降低
func main() {
sing1 := GetInstance()
sing1.SingFunc()
sing2 := GetInstance()
fmt.Printf("sing1:%p\tsing2:%p", sing1, sing2)
}
// 小写代表private,对外暴露GetInstance获取实例
var instance *singleton
type singleton struct {
}
func GetInstance() *singleton {
if instance == nil {
instance = new(singleton)
}
return instance
}
func (receiver singleton) SingFunc() {
fmt.Println("懒汉式的线程不安全方法。。。")
}
/*
懒汉式的线程不安全方法。。。
sing1:0xa80438 sing2:0xa80438
func main() {
sing1 := GetInstance()
sing1.SingFunc()
sing2 := GetInstance()
fmt.Printf("sing1:%p\tsing2:%p", sing1, sing2)
}
// 小写代表private,对外暴露GetInstance获取实例
var instance *singleton
var lock sync.Mutex
var initialized uint32
type singleton struct {
}
func GetInstance() *singleton {
// 标记位
if atomic.LoadUint32(&initialized) == 1 {
return instance
}
lock.Lock()
defer lock.Unlock()
if instance == nil {
instance = new(singleton)
atomic.StoreUint32(&initialized, 1)
}
return instance
}
func (receiver singleton) SingFunc() {
fmt.Println("懒汉式的线程安全方法。。。")
}
/*
懒汉式的线程安全方法。。。
sing1:0xc50460 sing2:0xc50460
添加标记位的目的就是减少加锁的次数,多线程时每次调用这个方法都要加锁判断效率会很低。
Go语言还有一种新的方法,就是 once,内容只执行一次,这样就简化了加锁实例
func main() {
sing1 := GetInstance()
sing1.SingFunc()
sing2 := GetInstance()
fmt.Printf("sing1:%p\tsing2:%p", sing1, sing2)
}
// 小写代表private,对外暴露GetInstance获取实例
var instance *singleton
var once sync.Once
type singleton struct {
}
func GetInstance() *singleton {
once.Do(func() {
instance = new(singleton)
})
return instance
}
func (receiver singleton) SingFunc() {
fmt.Println("懒汉式的线程安全方法。。。")
}
/*
懒汉式的线程安全方法。。。
sing1:0xc70458 sing2:0xc70458
工厂模式
简单工厂模式
func main() {
fruitfactory := FruitFactory{}
apple := fruitfactory.CreatFruit("apple")
apple.show()
pear := fruitfactory.CreatFruit("pear")
pear.show()
}
type FruitFactory struct {
}
type apple struct {
}
type pear struct {
}
type Fruit interface {
show()
}
func (receiver apple) show() {
fmt.Println("苹果。。。")
}
func (receiver pear) show() {
fmt.Println("梨子。。。")
}
func (receiver FruitFactory) CreatFruit(fruit string) Fruit {
switch fruit {
case "apple":
return apple{}
case "pear":
return pear{}
}
return nil
}
/*
苹果。。。
梨子。。。
工厂方法模式
func main() {
applefactory := new(appleFactory)
apple := applefactory.CreatFruit()
apple.Show()
var pearfactory FruitFactory
pearfactory = new(pearFactory)
pear := pearfactory.CreatFruit()
pear.Show()
}
type FruitFactory interface {
CreatFruit() Fruit
}
type Fruit interface {
Show()
}
type appleFactory struct {
}
type pearFactory struct {
}
type apple struct {
}
func (receiver apple) Show() {
fmt.Println("苹果。。。。")
}
type pear struct {
}
func (receiver pear) Show() {
fmt.Println("梨子。。。。")
}
func (receiver appleFactory) CreatFruit() Fruit {
return apple{}
}
func (receiver pearFactory) CreatFruit() Fruit {
return pear{}
}
/*
苹果。。。。
梨子。。。。
抽象工厂模式
func main() {
var chinaFactory Factory
chinaFactory = new(ChinaFactory)
chinaApple := chinaFactory.CreatApple()
chinaApple.show()
usaFactory := USAFactory{}
usaPear := usaFactory.CreatPear()
usaPear.show()
}
// 抽象层
type Factory interface {
CreatApple() Apple
CreatPear() Pear
}
type Apple interface {
show()
}
type Pear interface {
show()
}
// 中国工厂
type ChinaFactory struct {
}
type ChinaApple struct {
}
type ChinaPear struct {
}
func (receiver ChinaFactory) CreatApple() Apple {
return ChinaApple{}
}
func (receiver ChinaFactory) CreatPear() Pear {
return ChinaPear{}
}
func (receiver ChinaApple) show() {
fmt.Println("中国的苹果。。。")
}
func (receiver ChinaPear) show() {
fmt.Println("中国的梨子。。。")
}
// 美国工厂
type USAFactory struct {
}
type USAApple struct {
}
type USAPear struct {
}
func (receiver USAFactory) CreatApple() Apple {
return USAApple{}
}
func (receiver USAFactory) CreatPear() Pear {
return USAPear{}
}
func (receiver USAApple) show() {
fmt.Println("美国的苹果。。。")
}
func (receiver USAPear) show() {
fmt.Println("美国的梨子。。。")
}
/*
中国的苹果。。。
美国的梨子。。。
原型模式
用于创建重复的对象,同时又能保证性能,当直接创建对象的代价比较大时,则采用这种模式。一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
浅拷贝、深拷贝
func main() {
Manager = NewCellsManager()
细胞1 := &Cell{
ID: 1,
}
fmt.Printf("细胞1:%p\n", 细胞1)
Manager.Set("标号1", 细胞1)
fmt.Printf("缓存中的细胞1:%p\n", Manager.Get("标号1"))
细胞2 := Manager.Get("标号1").Clone()
fmt.Printf("细胞2:%p\n", 细胞2)
}
var Manager *CellsManager
type CloneCache interface {
Clone() CloneCache
}
type Cell struct {
ID uint32
}
func (receiver *Cell) Clone() CloneCache {
cloneCell := *receiver
return &cloneCell
}
type CellsManager struct {
cloneCache map[string]CloneCache
}
func NewCellsManager() *CellsManager {
return &CellsManager{
cloneCache: make(map[string]CloneCache),
}
}
func (receiver *CellsManager) Set(name string, cloneCache CloneCache) {
receiver.cloneCache[name] = cloneCache
}
func (receiver *CellsManager) Get(name string) CloneCache {
return receiver.cloneCache[name]
}
/*
细胞1:0xc00000a098
缓存中的细胞1:0xc00000a098
细胞2:0xc00000a0cc
细胞2和细胞1的地址不同,也说明是从Cache中拷贝出来的新对象
建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象,一个 Builder 类一步一步构造最终的对象,该 Builder 类是独立于其他对象的。
面临着一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。将变与不变的分离开。
func main() {
mealBuilder = NewMealBuilder()
张三 := Meal{
Items: make(map[string]Item),
sum: 0,
}
张三.AddItem("蔬菜汉堡", mealBuilder.BurgerMeal.vegBurger)
张三.AddItem("可乐", mealBuilder.DrinkMeal.cock)
张三.AddItem("鸡肉汉堡", mealBuilder.BurgerMeal.chickenBurger)
张三.AddItem("果汁", mealBuilder.DrinkMeal.juice)
张三.ShowItems()
张三.GetSum()
fmt.Println("一共花费:", 张三.sum, "元")
}
var mealBuilder *MealBuilder
type Item interface {
GetPrice() float64
}
type VegBurger struct {
}
type ChickenBurger struct {
}
type Coke struct {
}
type Juice struct {
}
func (receiver VegBurger) GetPrice() float64 {
return 8.0
}
func (receiver ChickenBurger) GetPrice() float64 {
return 10.0
}
func (receiver Coke) GetPrice() float64 {
return 5.8
}
func (receiver Juice) GetPrice() float64 {
return 4.3
}
type Burger struct {
vegBurger VegBurger
chickenBurger ChickenBurger
}
type Drink struct {
cock Coke
juice Juice
}
type Meal struct {
Items map[string]Item
sum float64
}
func (receiver *Meal) AddItem(name string, item Item) {
receiver.Items[name] = item
}
func (receiver *Meal) GetSum() {
receiver.sum = 0
for _, item := range receiver.Items {
receiver.sum += item.GetPrice()
}
}
func (receiver *Meal) ShowItems() {
fmt.Println("--- 账单 ---")
for name, item := range receiver.Items {
fmt.Println(name, ":", item.GetPrice(), "元")
}
fmt.Println("------------")
}
type MealBuilder struct {
BurgerMeal *Burger
DrinkMeal *Drink
}
func NewMealBuilder() *MealBuilder {
return &MealBuilder{
BurgerMeal: new(Burger),
DrinkMeal: new(Drink),
}
}
/*
--- 账单 ---
果汁 : 4.3 元
蔬菜汉堡 : 8 元
可乐 : 5.8 元
鸡肉汉堡 : 10 元
------------
一共花费: 28.1 元