模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端,客户只知道一个类就可以了。
程序实例:商场促销。

package main

import (
	"fmt"
)

type CashSuper interface {
	AcceptCash(price float64) float64
}

//正常
type CashNormal struct {
}

func (this *CashNormal) AcceptCash(price float64) float64 {
	if price < 0 {
		panic("不允许负数作为参数")
	}
	return price
}

type CashRebate struct {
	condition float64
	rebate    float64
}

// 满减
func (this *CashRebate) AcceptCash(price float64) float64 {
	if price < 0 || this.condition < 0 || this.rebate < 0 {
		panic("不允许负数作为参数")
	}
	if price >= this.condition {
		return price - float64(int(price/this.condition))*this.rebate
	} else {
		return price
	}
}

type CashDiscount struct {
	discount float64
}

// 折扣
func (this *CashDiscount) AcceptCash(price float64) float64 {
	if price < 0 || this.discount < 0 {
		panic("不允许负数作为参数")
	}
	if this.discount >= 1 {
		panic("折扣无效")
	}
	return price * this.discount
}

type CashContext struct {
	cs CashSuper
}

func (this *CashContext) GetResult(price float64) float64 {
	return this.cs.AcceptCash(price)
}

func NewCashContext(style string) *CashContext {
	context := &CashContext{}
	switch style {
	case "正常收费":
		context.cs = &CashNormal{}
	case "满300返100":
		context.cs = &CashRebate{300, 100}
	case "8折":
		context.cs = &CashDiscount{0.8}
	default:
		panic("计价方式错误!")
	}

	return context
}

func main() {
	var total float64
	cash1 := NewCashContext("正常收费")
	total += cash1.GetResult(1 * 10000)
	cash2 := NewCashContext("满300返100")
	total += cash2.GetResult(1 * 10000)
	cash3 := NewCashContext("8折")
	total += cash3.GetResult(1 * 10000)
	fmt.Println("total:", total)
}