七、观察者模式
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()
}