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

七、观察者模式

1.作用

当对象间存在一对多关系时,则使用观察者模式。比如,当一个对象被修改时,则会自动通知依赖它的对象。

2.举例

1、创建 Observer 类
type Observer interface {
	Notify(interface{})
}
2、创建 Subject 类
type Subject struct {
	observers []Observer
	state     string
}

func (s *Subject)SetState(state string) {
	s.state = state
	s.NotifyAllObservers()
}
func (s *Subject)Attach(observer ... Observer) {
	s.observers = append(s.observers, observer ...)
}

func (s *Subject)NotifyAllObservers() {
	for _, obs := range s.observers {
		obs.Notify(s)
	}
}
3、创建实体观察者类
type AObserver struct {
	Id string
}

func (ao *AObserver)Notify(sub interface{}) {
	fmt.Println(ao.Id , " receive ", sub.(*Subject).state)
}
4、测试
func TestObserver(t *testing.T) {
	sub := &Subject{}
	a := &AObserver{Id:"A"}
	b := &AObserver{Id:"b"}
	sub.Attach(a,b)
	sub.SetState("hello world")
	sub.SetState("i know")
}

八、状态模式

1.作用

核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!
就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,
而且你的好友也能看到你的状态, 所以,状态模式就两点:
1、可以通过改变状态来获得不同的行为。
2、你的好友能同时看到你的变化

2.举例

1、创建实体类
// 灯
type Light struct {
     State LightState
}

func(l *Light)PressSwitch(){
	if l.State!=nil {
		l.State.PressSwitch(l)
	}
}

2、创建状态接口
// 灯状态
type LightState  interface {
	PressSwitch(light *Light)
}
3、实现多种状态
// 开灯状态
type OnLightState struct {

}

// 开灯
func(ols *OnLightState)PressSwitch(light *Light){
	fmt.Println("turn on light")
	// 下一个状态动作为关灯
	light.State=&OffLightState{}
}

// 关灯状态
type OffLightState struct {

}

// 关灯
func(ols *OffLightState)PressSwitch(light *Light){
	fmt.Println("turn off light")
	// 下一个状态动作为开灯
	light.State=&OnLightState{}
}
4、测试
// 切换状态
func TestState(t *testing.T) {
	light:=&Light{State:&OnLightState{}}
	light.PressSwitch()
	light.PressSwitch()
}

九、策略模式

1.作用

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为

2.举例

1、创建策略接口
type Strategy interface {
	Do(interface{})
}
2、创建上下文类
// 从A到B
type AToB struct {
	// 距离
	ABDistance float64
        // 到达方式策略
	Strategy Strategy
}

func(ab *AToB) Do(){
	if ab.Strategy!=nil {
		ab.Strategy.Do(ab)
	}
}
3、实现多个策略
// 自行车策略
type BikeStrategy struct {
	Speed float64
}

func (bs *BikeStrategy) Do(ab interface{}) {
	aTob, ok := ab.(*AToB)
	if ok && bs.Speed <= 0.0000001 {
		return
	}
	fmt.Println("方式:自行车 用时:", aTob.ABDistance/bs.Speed)
}

// 巴士策略
type BusStrategy struct {
	Speed float64
}

func (bs *BusStrategy) Do(ab interface{}) {
	aTob, ok := ab.(*AToB)
	if ok && bs.Speed <= 0.0000001 {
		return
	}
	fmt.Println("方式:巴士 用时:", aTob.ABDistance/bs.Speed)
}

// 飞机策略
type AirStrategy struct {
	Speed float64
}

func (as *AirStrategy) Do(ab interface{}) {
	aTob, ok := ab.(*AToB)
	if ok && as.Speed <= 0.0000001 {
		return
	}
	fmt.Println("方式:飞机 用时:", aTob.ABDistance/as.Speed)
}

4、测试
func TestStrategy(t *testing.T) {
	aTob := &AToB{ABDistance: 600}

	aTob.Strategy = &BikeStrategy{Speed: 15}
	aTob.Do()

	aTob.Strategy = &BusStrategy{Speed: 90}
	aTob.Do()

	aTob.Strategy = &AirStrategy{Speed: 500}
	aTob.Do()
}

十、模板模式

1.作用

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。

2.举例

1、创建模板方法
type Game interface {
	Start()
	Playing()
	End()
}
2、创建实现的基本类
type AbsGame struct {
}

func (ag *AbsGame) Start() {
	fmt.Println("start game")
}
func (ag *AbsGame) Playing() {
	fmt.Println("game playing")
}
func (ag *AbsGame) End() {
	fmt.Println("the end")
}

3、不同实例实现模板中的方法
type FootBall struct {
	*AbsGame
}

func (fb *FootBall) Playing() {
	fmt.Println("playing FootBall")
}

type Cricket struct {
	*AbsGame
}

func (fb *Cricket) Playing() {
	fmt.Println("playing Cricket ")
}
4、通用的调用模板方法流程
func RunGame(g Game) {
	g.Start()
	g.Playing()
	g.End()
}
5、测试
func TestStrategy(t *testing.T) {
	aTob := &AToB{ABDistance: 600}

	aTob.Strategy = &BikeStrategy{Speed: 15}
	aTob.Do()

	aTob.Strategy = &BusStrategy{Speed: 90}
	aTob.Do()

	aTob.Strategy = &AirStrategy{Speed: 500}
	aTob.Do()
}

十一、访问者模式

1.作用

意图:主要将数据结构与数据操作分离。
主要解决:稳定的数据结构和易变的操作耦合问题。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

2.举例

1、创建访问者接口
type Game interface {
	Start()
	Playing()
	End()
}
2、创建数据结构类,并定义接受访问者方法
type ABData struct {
	A int
	B int
}
func (as *ABData)Accept(vi Visitor){
	vi.Visit(as)
}
3、实现不同的访问者
type FootBall struct {
	*AbsGame
}

func (fb *FootBall) Playing() {
	fmt.Println("playing FootBall")
}

type Cricket struct {
	*AbsGame
}

func (fb *Cricket) Playing() {
	fmt.Println("playing Cricket ")
}
4、测试
func RunGame(g Game) {
	g.Start()
	g.Playing()
	g.End()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值