设计模式学习笔记-行为型模式(上)

设计模式golang-行为型模式(上)

一、责任链模式

1.作用

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

2.举例

1、定义处理请求接口
// 处理事件
type ScreenEvent struct {
	Type string
	Comment string
}

// 定义处理事件的方法
type IScreenEventHandler interface{
	Handle(*ScreenEvent)bool
	SetNextHandler(IScreenEventHandler)
}

2、创建抽象类
// 兜底处理器
type AbsScreenEventHandler struct {
	NextHandler IScreenEventHandler
}

func(ase *AbsScreenEventHandler)Handle(se *ScreenEvent)bool{
	if ase.NextHandler!=nil {
		return ase.NextHandler.Handle(se)
	}
	return false
}

func(ase *AbsScreenEventHandler)SetNextHandler(ise IScreenEventHandler){
	ase.NextHandler=ise
}
3、创建实体类
type HomeScreenEventHandler  struct {
	AbsScreenEventHandler
}

func(hse *HomeScreenEventHandler)Handle(se *ScreenEvent)bool{
	fmt.Println("HomeScreenEventHandler.....")
	if se.Type=="HomeClick" {
		fmt.Println("HomeClick")
		return true
	}
	return hse.AbsScreenEventHandler.Handle(se)
}

type UserScreenEventHandler  struct {
	AbsScreenEventHandler
}

func(use *UserScreenEventHandler)Handle(se *ScreenEvent)bool{
	fmt.Println("UserScreenEventHandler.....")
	if se.Type=="UserModelClick" {
		fmt.Println("UserModelClick")
		return true
	}
	return use.AbsScreenEventHandler.Handle(se)
}
4、组装成责任链
var (
	osd IScreenEventHandler
)

func init()  {
	osd=&AbsScreenEventHandler{}
	home:=&HomeScreenEventHandler{}
	user:=&UserScreenEventHandler{}
	// 设置下一个责任链
	home.SetNextHandler(user)
	osd.SetNextHandler(home)
}
5、测试
func TestChainOfResponsibility(t *testing.T) {
	screenEvent:=&ScreenEvent{Type:"HomeClick"}
	osd.Handle(screenEvent)

	//fmt.Println("-----------------------------------------------\n")
	screenEvent=&ScreenEvent{Type:"UserModelClick"}
	osd.Handle(screenEvent)

	//fmt.Println("-----------------------------------------------\n")
	screenEvent=&ScreenEvent{Type:"Null"}
	osd.Handle(screenEvent)
}

二、命令模式

1.作用

意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

如何解决:通过调用者调用接受者执行命令,顺序:调用者→命令→接受者。

2.举例

1、创建一个命令接口
// 命令接口
type Command interface {
	Do(args interface{}) (interface{}, error)
}
2、创建多个请求类
// Get 命令
type GetCommand struct {
}

func (gc *GetCommand) Do(args interface{}) (interface{}, error) {
	fmt.Println("GetCommand")
	return args, nil
}

// post 命令
type PostCommand struct {
}

func (pc *PostCommand) Do(args interface{}) (interface{}, error) {
	fmt.Println("PostCommand")
	return args, nil
}
3、创建命令管理者 创建注册方法->定义请求命令请求参数->处理命令
// 命令管理者
type CommandHandler struct {
	CmdMap map[string]Command
}

// 注册命令
func (ch *CommandHandler) Register(cmdType string, cmd Command) {
	ch.CmdMap[cmdType] = cmd
}

// 处理上下文
type CmdContext struct {
	CmdType string
	Args    interface{}
}

// 处理命令
func (ch *CommandHandler) Handle(ctx *CmdContext) (interface{}, error) {
	if ctx == nil {
		return nil, errors.New("")
	}
	cmd, ok := ch.CmdMap[ctx.CmdType]
	if ok {
		return cmd.Do(ctx.Args)
	}
	return nil, errors.New("invalid Command ")
}
// 命令接口
type Command interface {
	Do(args interface{}) (interface{}, error)
}
4、初始化,注册多个命令
var (
	// 命令处理者
	cmdHandler = &CommandHandler{CmdMap: make(map[string]Command)}
)

func init()  {
	cmdHandler.Register("post", &PostCommand{})
	cmdHandler.Register("get", &GetCommand{})
}
5、测试
func TestCommand(t *testing.T) {
	postCtx := &CmdContext{CmdType: "post", Args: " Post"}
	getCtx := &CmdContext{CmdType: "get", Args: " Get"}
	nullCtx := &CmdContext{CmdType: "null", Args: " Get"}
	fmt.Println(cmdHandler.Handle(postCtx))
	fmt.Println(cmdHandler.Handle(getCtx))
	fmt.Println(cmdHandler.Handle(nullCtx))
}

三、解释器模式

1、创建一个表达式接口
// 表达式接口
type Expression interface {
	Interpret(context string) bool
}

2、创建实现了上述接口的多个实体类
// 终结符
type TerminalExpression struct {
	Word string
}

func(te *TerminalExpression)Interpret(context string) bool{
	if strings.Contains(context,te.Word) {
		return true
	}
	return false
}

// 或
type OrExpression struct {
	A Expression
	B Expression
}

func(oe *OrExpression)Interpret(context string) bool{
	return oe.A.Interpret(context)||oe.B.Interpret(context)
}

// 与
type AndExpression  struct {
	A Expression
	B Expression
}

func(ae *AndExpression )Interpret(context string) bool{
	return ae.A.Interpret(context)&&ae.B.Interpret(context)
}
3、测试
func TestInterpreterTest(t *testing.T) {
	isMale :=&OrExpression{&TerminalExpression{"Robert"},&TerminalExpression{"John"}}
	isMarriedWoman :=&AndExpression{&TerminalExpression{"Julie"},&TerminalExpression{"Married"}}
	fmt.Println("John is male?",isMale.Interpret("John"))
	fmt.Println("Julie is a married women?",isMarriedWoman.Interpret("Married Julie"))
}

四、迭代器模式

1.作用

这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

2.举例

1、创建迭代器接口和集合接口
// 迭代器接口
type Iterator interface {
	HasNext() bool
	Next() interface{}
}

// 集合接口
type Container interface {
	GetIterator() Iterator
}
2、创建实现接口的实体类
// 数组迭代器
type ArrayIterator struct {
	currentIndex int
	ac           *ArrayContainer
}

func (ai *ArrayIterator) HasNext() bool {
	if ai.ac.arrayData!=nil&&ai.currentIndex < len(ai.ac.arrayData) {
		return true
	}
	return false
}

func (ai *ArrayIterator) Next() interface{} {
	if ai.HasNext() {
		defer func() { ai.currentIndex++ }()
		return ai.ac.arrayData[ai.currentIndex]

	}
	return nil
}

// 数组集合
type ArrayContainer struct {
	arrayData []interface{}
}

func (ac *ArrayContainer) GetIterator() Iterator {
	return &ArrayIterator{currentIndex: 0, ac: ac}
}
3、测试
func TestIteratorTest(t *testing.T) {
	arr:=[]interface{}{"a","b","c","d"}
	arrayContainer:=&ArrayContainer{arrayData:arr}
	iterator:=arrayContainer.GetIterator()
	for iterator.HasNext(){
		fmt.Println(iterator.Next().(string))
	}
}

五、中介者模式

1.作用

用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。

2.效果

已中介者为中心。其他对象的通信都需要连接中介者

3.举例

1、创建中介类
type ChatRoom struct {
       name string
}

func (cr *ChatRoom)SendMsg(msg string){
	fmt.Println(cr.name+" : "+msg)
}
func (cr *ChatRoom)RegisterUser(u *User){
	u.cr=cr
}
2、创建 user 类
type User struct {
	name string
	cr *ChatRoom
}

func (u *User)SendMsg(msg string){
	if u.cr!=nil {
		u.cr.SendMsg(u.name+" : "+msg)
	}
}
3、使用 User 对象来显示他们之间的通信
func TestMediator(t *testing.T) {
	AUser:=&User{name:"AUser"}
	BUser:=&User{name:"BUser"}

	chatRoom:=&ChatRoom{name:"chatRoom123456"}
	chatRoom.RegisterUser(AUser)
	chatRoom.RegisterUser(BUser)

	AUser.SendMsg("hello AUser")
	BUser.SendMsg("hello BUser")
}

六、备忘录模式

1.作用

保存一个对象的某个状态,以便在适当的时候恢复对象。
所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

2.举例

1、创建存储在备忘录中的实体类
// 文本编辑
type Text struct {
	Value string
}

// 写
func (t *Text) Write(value string) {
	t.Value = value
}

// 读取
func (t *Text) Read() string {
	return t.Value
}
2、创建备忘录
// 备忘结构
type Memento struct {
	Value string
}

// 备忘
func (t *Text) SaveToMemento() *Memento {
	return &Memento{Value: t.Value}
}

// 从备忘恢复
func (t *Text) RestoreFromMemento(m *Memento) {
	if m != nil {
		t.Value = m.Value
	}
	return
}
3、管理备忘录
// 管理备忘记录
type Storage struct {
	*list.List
}

// Back returns the last element of list l or nil.
// and remove form list
func (s *Storage) RPop() *list.Element {
	ele := s.Back()
	if ele != nil {
		s.Remove(ele)
	}
	return ele
}

4、测试
func TestMemento(t *testing.T) {
	storage := &Storage{list.New()}
	text := &Text{"hello world"}
	fmt.Println(text.Read())
	storage.PushBack(text.SaveToMemento())
	text.Write("nihao")
	fmt.Println(text.Read())
	storage.PushBack(text.SaveToMemento())
	text.Write("i know")
	fmt.Println(text.Read())

	//后退回滚
	mediator := storage.RPop()
	if mediator != nil {
		text.RestoreFromMemento(mediator.Value.(*Memento))
	}
	fmt.Println(text.Read())

	//后退回滚
	mediator = storage.RPop()
	if mediator != nil {
		text.RestoreFromMemento(mediator.Value.(*Memento))
	}
	fmt.Println(text.Read())

	//后退 已没有
	mediator = storage.RPop()
	if mediator != nil {
		text.RestoreFromMemento(mediator.Value.(*Memento))
	}
	fmt.Println(text.Read())
}

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