【Golang设计模式】工厂、单例、建造者、桥接、命令、迭代器模式

golang设计模式

  • 一、工厂模式
    • 1、普通工厂
    • 2、抽象工厂
      • 简单抽象工厂
      • 完全体抽象工厂
  • 二、单例模式
    • 1、饿汉式
    • 2、懒汉式
  • 三、建造者模式
  • 四、桥接模式
  • 五、命令模式
  • 六、迭代器模式

一、工厂模式

// Shape接口
type Shape interface {
	draw()
}
type Circle struct {}
func (s *Circle) draw() {
	fmt.Println("Circle")
}
type Square struct {}
func (s *Square) draw() {
	fmt.Println("Square")
}

// Color接口
type Color interface {
	fill()
}
type Red struct {}
func (s *Red) fill() {
	fmt.Println("Red")
}
type Blue struct {}
func (s *Blue) fill() {
	fmt.Println("Blue")
}
type Green struct {}
func (s *Green) fill() {
	fmt.Println("Green")
}

1、普通工厂

// Shape工厂
func ShapeFactory(shape string) Shape {
	switch shape {
		case "circle":
			return &Circle{}
		case "square":
			return &Square{}
		default:
			return nil
	}
}
// Color工厂
func ColorFactory(color string) Color {
	switch color {
		case "red":
			return &Red{}
		case "blue":
			return &Blue{}
		case "green":
			return &Green{}
		default:
			return nil
	}
}

func main() {
	// shape工厂实例化
	shape := ShapeFactory("circle")
	shape.draw() // 输出 => "Circle"
	
	// color工厂实例化
	color := ColorFactory("red")
	color.fill() // 输出 => "Red"
}

2、抽象工厂

工厂封装在抽象工厂中统一获取对应的工厂
通过抽象工厂封装了Shape和Color的工厂类,从抽象工厂中获取工厂,在获取工厂对应的生产实例。

简单抽象工厂

// 抽象工厂
type AbstractFactory interface {
	getShape(string) Shape
	getColor(string) Color
}
type FactoryProducer struct {}
func NewFactoryProducer() AbstractFactory {
	return &FactoryProducer{}
}
// 抽象工厂:Shape工厂
func (f *FactoryProducer) getShape(shape string) Shape {
	switch shape {
		case "circle":
			return &Circle{}
		case "square":
			return &Square{}
		default:
			return nil
	}
}
// 抽象工厂:Color工厂
func (f *FactoryProducer) getColor(color string) Color {
	switch color {
		case "red":
			return &Red{}
		case "blue":
			return &Blue{}
		case "green":
			return &Green{}
		default:
			return nil
	}
}

func main() {
	// 抽象工厂
	abstractFactory	:= NewFactoryProducer()
	
	// 抽象工厂:Shape工厂
	shape := abstractFactory.getShape("circle")
	shape.draw() // 输出 => "Circle"
	
	// 抽象工厂:Color工厂
	color := abstractFactory.getColor("blue")
	color.fill() // 输出 => "Blue"
}

完全体抽象工厂

// ==== 颜色 ====
type Color interface {
	color()
}
type Red struct {}
func (this *Red) color() {
	fmt.Println("红色")
}
type Yellow struct {}
func (this *Yellow) color() {
	fmt.Println("黄色")
}
type Blue struct {}
func (this *Blue) color() {
	fmt.Println("蓝色")
}

// ==== 形状 ====
type Shape interface {
	shape()
}
type Circular struct {}
func (this *Circular) shape() {
	fmt.Println("圆形")
}
type Square struct {}
func (this *Square) shape() {
	fmt.Println("正方形")
}


// ===== 抽象工厂 =====
type AbstractFactory interface {
	ColorFactory(color string) Color // 颜色工厂
	ShapeFactory(shape string) Shape // 形状工厂
}
// 形状工厂
type ShapeFactory struct {}
func (factory *ShapeFactory) ColorFactory(color string) Color {
	return nil
}
func (factory *ShapeFactory) ShapeFactory(shape string) Shape {
	switch shape {
		case "cir":
			return &Circular{}
		case "square":
			return &Square{}
		default:
			return nil
	}
}
// 颜色工厂
type ColorFactory struct {}
func (factory *ColorFactory) ColorFactory(color string) Color {
		switch color {
			case "red":
				return &Red{}
			case "yellow":
				return &Yellow{}
			case "blue":
				return &Blue{}
			default:
				return nil
		}
}
func (factory *ColorFactory) ShapeFactory(shape string) Shape {
	return nil
}

// 总工厂 选择 子工厂
func NewFactory(choice string) AbstractFactory {
	switch choice {
		case "shape":
			return &ShapeFactory{}
		case "color":
			return &ColorFactory{}
		default:
			return nil
	}
}

func Try() {
	colorFactory := NewFactory("color")
	colorFactory.ColorFactory("red").color()
	shapFactory := NewFactory("shape")
	shapFactory.ShapeFactory("cir").shape()
}

二、单例模式

1、饿汉式

好处:初始化就加载,不用担心多线程多次创建
坏处:初始化就加载,如果相对耗时,初始化加载时间会延长

type SingleObject struct {}
var instance *SingleObject = &SingleObject{}
func getInstance() *SingleObject {
	return instance
}

2、懒汉式

  1. 默认懒汉
    type SingleObject struct {}
    var instance *SingleObject
    func getInstance() *SingleObject {
    	if instance == nil {
    		instance = &SingleObject{}
    	}
    	return instance
    }
    
  2. 懒汉加锁(避免多线程操作)
    方式1:这种方法可能会导致所有线程阻塞
    var mutex sync.Mutex
     
    type SingleObject struct {}
    var instance *SingleObject
    func getInstance() *SingleObject {
    	mutex.Lock()
    	defer mutex.UnLock()
    	
    	if instance == nil {
    		instance = &SingleObject{}
    	}
    	return instance
    }
    
    方式2:once.Do第一次加载时执行的代码,避免加锁阻塞
    var once sync.Once
     
    type SingleObject struct {}
    var instance *SingleObject
    func getInstance() *SingleObject {
    	 once.Do(func(){
    		 instance = &SingleObject{}
    	 })
    	return instance
    }
    

三、建造者模式

建造者模式可以理解为,一层一层的建造。将一块的业务逻辑抽离,由底层分解。


理解:
比如,吃汉堡,需要包装纸(包装属于一个类),汉堡使用纸包装,汉堡是所有品种的大类,具体类可以是蔬菜汉堡、炸鸡煲等。这些创建好,需要一个统一的点菜类,这个类可以添加菜品,可以显示当前点菜的数量,总价等。我们甚至可以依赖此类,来做一个套餐方法,基础菜品默认添加到该套餐内。


理解如下图【Golang设计模式】工厂、单例、建造者、桥接、命令、迭代器模式_第1张图片

  1. 创建包装类
    // ===== 包装类 =====
    type Packing interface {
    	Pack() string
    }
    
    // 包装:纸
    type Wrapper struct {}
    func (this *Wrapper) Pack() string {
    	return "Wrapper"
    }
    // 包装:杯
    type Bottle struct {}
    func (this *Bottle) Pack() string {
    	return "Bottle"
    }
    
  2. 创建品类结构体
    // ===== 品类 =====
    type Item interface {
    	Green() 	bool		// 是否健康
    	Packing() 	Packing		// 包装
    	Name() 		string  	// 名称
    	Price() 	float64 	// 价格
    }
    
  3. 创建品类的大类
    // 汉堡父类
    type Burger struct {}
    func (s *Burger) Green() bool {
    	return false
    }
    func (burger *Burger) Packing() Packing {
    	return &Wrapper{}
    }
    func (burger *Burger) Name() string { return "" }
    func (burger *Burger) Price() float64 { return 0.0 }
    
    // 冷饮父类
    type ColdDrink struct {}
    func (s *ColdDrink) Green() bool {
    	return true
    }
    func (coldDrink *ColdDrink) Packing() Packing {
    	return &Bottle{}
    }
    func (coldDrink *ColdDrink) Name() string { return ""	}
    func (coldDrink *ColdDrink) Price() float64 { return 0.0 }
    
  4. 汉堡子类
    // 蔬菜汉堡
    type VegBurger struct {
    	Burger
    }
    func (coldDrink *VegBurger) Name() string { return "蔬菜汉堡"	}
    func (coldDrink *VegBurger) Price() float64 { return 12.5 }
    
    // 炸鸡汉堡
    type ChickenBurger struct {
    	Burger
    }
    func (coldDrink *ChickenBurger) Name() string { return "炸鸡汉堡"	}
    func (coldDrink *ChickenBurger) Price() float64 { return 22.5 }
    
  5. 冷饮子类
    // 可口可乐
    type Coker struct {
    	ColdDrink
    	Category string // 品类
    }
    func (coldDrink *Coker) Name() string { return "可口可乐"	}
    func (coldDrink *Coker) Price() float64 { return 3.0 }
    
    // 牛奶
    type Milk struct {
    	ColdDrink
    	Category string // 品类
    }
    func (coldDrink *Milk) Name() string { return "牛奶"	}
    func (coldDrink *Milk) Price() float64 { return 6.0 }
    
  6. 套餐类
    type Meal struct {
    	item []Item
    }
    // 添加食物
    func (this *Meal) AddItem(item Item) {
    	this.item = append(this.item, item)
    }
    func (this *Meal) ShowAllPrice() float64 {
    	prices := 0.0
    	for i := 0; i < len(this.item); i++ {
    		prices += this.item[i].Price()
    	}
    	fmt.Println("总价:", prices)
    	return prices
    }
    // 显示食物
    func (this *Meal) ShowItem() {
    	for _, item := range this.item {
    		fmt.Println("名称:", item.Name())
    		fmt.Println("包装:", item.Packing().Pack())
    		fmt.Println("价格:", item.Price())
    	}
    }
    
  7. 创建套餐
    func Package01() Meal {
    	meal := Meal{
    		item: []Item{},
    	}
    	meal.AddItem(&VegBurger{})
    	meal.AddItem(&ChickenBurger{})
    	meal.AddItem(&Coker{})
    	return meal
    }
    

四、桥接模式

桥接可以理解为 灵魂和肉体,灵魂为轴心不变,肉体可以随意选择
如下案例可以理解为圆是灵魂,颜色是肉体

  1. 基础画笔类
    type Draw interface {
    	drawCircle(string)
    }
    type Circle01 struct {}
    func (this *Circle01) drawCircle(color string) {
    	fmt.Println("画圆01 [ color: " + color + " ]")
    }
    type Circle02 struct {}
    func (this *Circle02) drawCircle(color string) {
    	fmt.Println("画圆02 [ color: " + color + " ]")
    }
    
  2. 抽象类
    type Shape struct {
    	draw Draw
    }
    // 3
    func (this *Shape) Shape(draw Draw)  {
    	this.draw = draw
    }
    
  3. 抽象实体类
    type Circle struct {
    	shape Shape
    	color string
    }
    func InitCircle(color string, draw Draw) *Circle {
    	circle := &Circle{
    		color: color,
    	}
    	// 2
    	circle.shape.Shape(draw)
    	return 	circle
    }
    func (this *Circle) Draw() {
    	this.shape.draw.drawCircle(this.color)
    }
    
  4. 调用
    &bridge.Circle01{} 1 => Draw接口接收 2 => 传递给Shape 3
    func main(){
    	// 1
    	c1 := bridge.InitCircle("红色", &bridge.Circle01{})
    	c1.Draw() // 圆1
    	c1.shape.Shape(&bridge.Circle02{})
    	c1.Draw() // 圆2
    	c2 := bridge.InitCircle("黄色", &bridge.Circle02{})
    	c2.Draw() // 圆2
    }
    

    案例2:画家是灵魂,形状是肉体

    	type DrawImpl interface {
    		draw()
    	}
    	type DrawCricle struct {}
    	func (this *DrawCricle) draw(color string){
    		fmt.Println("圆形;",color)
    	}
    	type DrawSquare struct {}
    	func (this *DrawSquare) draw(color string){
    		fmt.Println("正方形;",color)
    	}
    	
    	type DrawAbstract interface {
    		DrawShape()
    	}
    	// 画家
    	type Painter struct {
    		DrawImpl
    	}
    	func NewPainter(draw DrawImpl) DrawAbstract {
    		return &Painter{draw}
    	}
    	func (this *Painter) DrawShape(){
    		this.draw()
    	}
    	
    	func main(){
    		painter := NewPainter(&DrawSquare{})
    		painter.DrawShape()
    	}
    

五、命令模式

  1. 股票

    type Stock struct {
    	name 		string // 库存
    	quantity 	int    // 数量
    }
    
    func (this *Stock) buy() {
    	this.quantity++
    	fmt.Println("买入:", this.name, this.quantity)
    }
    func (this *Stock) sell() {
    	this.quantity -= 10000
    	fmt.Println("卖出", this.name, this.quantity)
    }
    
  2. 购买股票需要订单,所有定义订单接口

    type Order interface {
    	execute() // 执行
    }
    
  3. 买卖需要对应订单操作

    // 买入股票
    type BuyStock struct {
    	stock *Stock
    }
    func NewBuyStock(stock *Stock) Order {
    	return &BuyStock{stock: stock}
    }
    func (this *BuyStock) execute() {
    	this.stock.buy()
    }
    // 卖出股票
    type SellStock struct {
    	stock *Stock
    }
    func NewSellStock(stock *Stock) Order {
    	return &SellStock{stock: stock}
    }
    func (this *SellStock) execute() {
    	this.stock.sell()
    }
    
  4. 股票操盘手命令

    // 股票操盘手
    type Operator struct {
    	orders []Order
    }
    func (this *Operator) takeOrder(order Order) {
    	this.orders = append(this.orders, order)
    }
    func (this *Operator) placeOrders() {
    	for _, order := range this.orders {
    		order.execute()
    	}
    	this.orders = []Order{}
    }
    // 。。。。。后续可以增加命令,比如回购股票等等的命令
    
  5. 操作

    func main(){
    	// 特斯拉股票
    	stock := &Stock{
    		name: "特斯拉",
    		quantity: 100000,
    	}
    
    	// 初始化买卖的操作
    	orderBuy := NewBuyStock(stock)
    	orderSell := NewSellStock(stock)
    
    	// 初始化操盘手
    	operator := Operator{
    		orders: []Order{},
    	}
    	// 先买三只股票
    	operator.takeOrder(orderBuy)
    	operator.takeOrder(orderBuy)
    	operator.takeOrder(orderBuy)
    	operator.placeOrders()
    	// 再买两只股票
    	operator.takeOrder(orderBuy)
    	operator.takeOrder(orderBuy)
    	operator.placeOrders()
    	// 卖出股票
    	operator.takeOrder(orderSell)
    	operator.placeOrders()
    }
    

六、迭代器模式

迭代器模式就是java中的Iterator,是一个思想实现的数据结构

  1. 迭代器接口
    type Iterator interface {
    	HasNext() 	bool
    	Next() 		interface{}
    }
    
  2. 实现迭代器
    type aggIterator struct {
    	index int
    	container *Container
    }
    func (this *aggIterator) HasNext() bool {
    	if this.index < len(this.container.Datas) {
    		return true
    	}
    	return false
    }
    func (this *aggIterator) Next() interface{} {
    	if this.HasNext() {
    		data := this.container.Datas[this.index]
    		this.index++
    		return data
    	}
    	return nil
    }
    
  3. 数据容器
    // 容器
    type Container struct {
    	Datas []interface{} 
    }
    func (this *Container) GetIterator() Iterator {
    	// 容器存放具体数据
    	// 迭代元素交给Iterator
    	return &aggIterator{
    		index: 0,
    		container: this,
    	}
    }
    
  4. 调用
    func main(){
    	datas := []interface{}{1,2,31,4,1,31,2}
    	container := &Container{
    		Datas: datas,
    	}
    	iterator := container.GetIterator()
    	for {
    		if a := iterator.Next(); a == nil {
    			break
    		} else {
    			fmt.Print(a,"\t")
    		}
    	}
    }
    

你可能感兴趣的:(设计模式,golang,golang,设计模式)