【Golang设计模式】模版、空对象、策略、备忘录、责任链、中介模式

一、模版模式

定义一个操作中的算法的骨架,而将实现逻辑步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
可以参考sort.quickSortInterface接口,将Len() int长度、Less(i, j int) bool比较、Swap(i, j int)交换,这些排序的具体实现逻辑交给用户实现。

  1. 定义模版接口
    type Template interface {
    	initialize()
    	startPlay()
    	endPlay()
    }
    
  2. 定义游戏父类
    type Game struct {
    	temp Template
    }
    // 实现模版方法
    func (this *Game) play()  {
    	this.temp.initialize()
    	this.temp.startPlay()
    	this.temp.endPlay()
    }
    
  3. 定义子类
    type PlayBasketball struct {
    	Game //继承父类
    }
    func (this *PlayBasketball) initialize() {
    	fmt.Println("初始化")
    }
    func (this *PlayBasketball) startPlay() {
    	fmt.Println("开始游戏")
    }
    func (this *PlayBasketball) endPlay() {
    	fmt.Println("结束游戏")
    }
    
    func NewPlayBasketball() *PlayBasketball {
    	ball := new(PlayBasketball)
    	ball.Game = Game{temp: ball}
    	return ball
    }
    
  4. 测试
    func main() {
    	ball := NewPlayBasketball()
    	ball.play()
    }
    

二、空对象模式

一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。

  1. 行为接口

    type AbstractInterface interface {
    	isNil() bool
    	getName() string
    }
    
  2. 空对象模式

    type AbstractObject struct {
    	name string
    }
    // ==== 真实对象 ====
    type RealObject struct {
    	*AbstractObject
    }
    func (this *RealObject) getName() string {
    	return this.name
    }
    func (this *RealObject) isNil() bool {
    	return false
    }
    
    // ==== 空对象 ====
    type NilObject struct {
    	AbstractObject
    }
    func (this *NilObject) getName() string {
    	return "nil"
    }
    func (this *NilObject) isNil() bool {
    	return true
    }
    
  3. 工厂

    var names = []string{"bob", "tom"}
    func Factory(name string) AbstractInterface {
    	for i := 0; i < len(names); i++ {
    		if name == names[i] {
    			return &RealObject{
    				&AbstractObject{ name: name },
    			}
    		}
    	}
    	// 不存在就返回模拟的空对象
    	return &NilObject{}
    }
    
  4. 测试

    func Try() {
    	fact01 := Factory("bob")
    	fact02 := Factory("tom")
    	fact03 := Factory("wang")
    	fmt.Println(fact01.getName())
    	fmt.Println(fact02.getName())
    	fmt.Println(fact03.getName())
    	fmt.Println(fact01.isNil())
    	fmt.Println(fact02.isNil())
    	fmt.Println(fact03.isNil())
    }
    

三、策略模式

一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

  1. 定义三个锦囊
    type Strategy interface {
    	doOperation(operation string)
    }
    
    type Operation01 struct {}
    func (this *Operation01) doOperation(operation string) {
    	fmt.Println("策略01:", operation)
    }
    type Operation02 struct {}
    func (this *Operation02) doOperation(operation string) {
    	fmt.Println("策略02:", operation)
    }
    type Operation03 struct {}
    func (this *Operation03) doOperation(operation string) {
    	fmt.Println("策略01:", operation)
    }
    
  2. 执行锦囊
    type Context struct {
    	strategy Strategy
    }
    func (this *Context) Execute(operation string) {
    	this.strategy.doOperation(operation)
    }
    
    func NewContext(strategy Strategy) *Context {
    	return &Context{
    		strategy: strategy,
    	}
    }
    
  3. 测试
    策略组合工厂模式
    // 打开一个锦囊
    func Open(option int) Strategy {
    	switch option {
    		case 1:
    			return &Operation01{}
    		case 2:
    			return &Operation02{}
    		case 3:
    			return &Operation03{}
    	}
    }
    func main(){
    	c1 := NewContext(Open(1))
    	c1.Execute()
    }
    

四、备忘录模式

单独创建一个对象,作为副本,将副本存在版本中保存修改历史记录。可以想象成git的版本控制,会比较好理解。

  1. 备份对象和历史版本对象
    // Note 备份
    type Memento struct {
    	state string
    }
    func (this *Memento) getState() string {
    	return this.state
    }
    
    // 备份历史版本
    type MementoVersion struct {
    	mementos []*Memento
    }
    func (this *MementoVersion) add(memento *Memento) {
    	this.mementos = append(this.mementos, memento)
    }
    func (this *MementoVersion) get(index int) *Memento {
    	return this.mementos[index]
    }
    
  2. 正文和备份
    // 正文
    type Note struct {
    	state string
    }
    func (this *Note) setState(state string) {
    	this.state = state
    }
    func (this *Note) getState() {
    	fmt.Println(this.state)
    }
    // 创建正文副本
    func (this *Note) saveStateToMemento() *Memento {
    	return &Memento{
    		state: this.state,
    	}
    }
    // 获取正文副本,并将状态保存给当前状态
    func (this *Note) getStateFromMemento(memento *Memento)  {
    	this.state = memento.getState()
    }
    
  3. 测试
    func Try() {
    	ori := &Note{}
    	car := &MementoVersion{}
    
    	ori.setState("修改第1次")
    	ori.setState("修改第2次")
    	car.add(ori.saveStateToMemento())
    	ori.setState("修改第3次")
    	car.add(ori.saveStateToMemento())
    	ori.setState("修改第4次")
    
    	ori.getState()
    	ori.getStateFromMemento(car.get(0)) // 将最初修改的历史版本 拿出来
    	ori.getState()
    	ori.getStateFromMemento(car.get(1))
    	ori.getState()
    }
    

五、责任链模式

可以想象成JS中的冒泡事件。由首层触发后,会一直向下执行,直到所有节点遍历完毕。

  1. 上代码,用心感受
    var (
    	INFO = 1
    	DEBUG = 2
    	ERROR = 3
    )
    
    // 接口
    type BaseLogger interface {
    	write(message string)
    	LogMessage(level int, message string)
    }
    
    // 父类实现
    type AbstractLogger struct {
    	Level int
    	nextLogger BaseLogger
    }
    // 设置下一个logger对象
    func (this *AbstractLogger) setNextLogger(nextLogger BaseLogger)  {
    	this.nextLogger = nextLogger
    }
    
  2. 定义三种类型的logger
    // ==== error logger ===== 
    type ErrorLogger struct {
    	*AbstractLogger
    }
    func (this *ErrorLogger) write(message string) {
    	fmt.Println("error:", message)
    }
    // log输出
    func (this *ErrorLogger) LogMessage(level int, message string) {
    	// 判断传入的level是否相等,相等执行当前对象的write方法
    	if this.Level == level {
    		this.write(message)
    	}
    	// 判断是否存在下一个节点,下一个存在则调用下一个节点的LogMessage
    	if this.nextLogger != nil {
    		this.nextLogger.LogMessage(level, message)
    	}
    }
    func NewErrorLogger() *ErrorLogger {
    	return &ErrorLogger{
    		&AbstractLogger{
    			Level: ERROR,
    			nextLogger: nil,
    		},
    	}
    }
    // ==== console logger ===== 
    type ConsoleLogger struct {
    	*AbstractLogger
    }
    func (this *ConsoleLogger) write(message string) {
    	fmt.Println("info:", message)
    }
    func (this *ConsoleLogger) LogMessage(level int, message string) {
    	if this.Level == level {
    		this.write(message)
    	}
    	if this.nextLogger != nil {
    		this.nextLogger.LogMessage(level, message)
    	}
    }
    func NewConsoleLogger() *ConsoleLogger {
    	return &ConsoleLogger{
    		&AbstractLogger{
    			Level: INFO,
    			nextLogger: nil,
    		},
    	}
    }
    // ==== debug logger ===== 
    type DebeugLogger struct {
    	*AbstractLogger
    }
    func (this *DebeugLogger) write(message string) {
    	fmt.Println("debug:", message)
    }
    func (this *DebeugLogger) LogMessage(level int, message string) {
    	if this.Level == level {
    		this.write(message)
    	}
    	if this.nextLogger != nil {
    		this.nextLogger.LogMessage(level, message)
    	}
    }
    func NewDebeugLogger() *DebeugLogger {
    	return &DebeugLogger{
    		&AbstractLogger{
    			Level: DEBUG,
    			nextLogger: nil,
    		},
    	}
    }
    
  3. 组合节点顺序
    func GetChainOfLoggers() BaseLogger {
    	consoleLogger := NewConsoleLogger()
    	errorLogger := NewErrorLogger()
    	debugLogger := NewDebeugLogger()
    	
    	// 设置console下一个节点是errlogger
    	consoleLogger.setNextLogger(errorLogger)
    	// 设置errorlogger节点下一个是debuglogger节点
    	errorLogger.setNextLogger(debugLogger)
    
    	// 返回栈定的节点
    	return consoleLogger
    }
    
  4. 测试
    func Try() {
    	loggerChain := GetChainOfLoggers()
    	// 会将整个链表遍历,找到与参数一箱等的level输出
    	loggerChain.LogMessage(INFO, "info")
    	loggerChain.LogMessage(ERROR, "error")
    	loggerChain.LogMessage(DEBUG, "debug")
    }
    

六、中介模式

将一对多转化成了一对一。 2、各个类之间的解耦.
想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类

var chatRoom = &ChatRoom{}
// 中介
type ChatRoom struct {}
func (this *ChatRoom) ShowMessage(user *User, message string)  {
	fmt.Println(time.Now(), user.getName(), ":", message)
}

type User struct {
	name string
}
func (this *User) setName(name string) {
	this.name = name
}
func (this *User) getName() string {
	return this.name
}
func (this *User) SendMessage(msg string) {
	chatRoom.ShowMessage(this, msg)
}

func main() {
	user := &User{
		name: "张三",
	}
	user.SendMessage("这是一个测试,看看效果")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼小鱼啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值