gof23结构类模式(golang版)

适配器模式

Adapter模式也被称为Wrapper模式,有以下两种:

  1. 类适配器(使用继承)

https://design-

image

实现目标接口,继承被适配类

  1. 对象适配器(使用委托)
image

继承目标类,依赖被适配类

参考http://blog.51cto.com/liuxp08...

package main

import (
    "fmt"
)

func main() {
    duck := &MallardDuck{}
    turkey := &WildTurkey{}

    turkeyAdapter := NewTurkeyAdapter(turkey)

    fmt.Println("The Turkey says...")
    turkey.gobble()
    turkey.fly()

    fmt.Println("The Duck says...")
    duck.quack()
    duck.fly()

    fmt.Println("The Turkey Adapter says...")
    turkeyAdapter.quack()
    turkeyAdapter.fly()
}

type Duck interface {
    quack()
    fly()
}

type Turkey interface {
    gobble()
    fly()
}

type MallardDuck struct {
}

func (*MallardDuck) quack() {
    fmt.Println("Quark...")
}

func (*MallardDuck) fly() {
    fmt.Println("flying...")
}

type WildTurkey struct {
}

func (*WildTurkey) gobble() {
    fmt.Println("Gobble...")
}

func (*WildTurkey) fly() {
    fmt.Println("flying a short distance")
}

type TurkeyAdapter struct {
    turkey Turkey
}

func NewTurkeyAdapter(turkey Turkey) *TurkeyAdapter {
    return &TurkeyAdapter{turkey}
}

func (this *TurkeyAdapter) quack() {
    this.turkey.gobble()
}

func (this *TurkeyAdapter) fly() {
    for i := 0; i < 5; i++ {
        this.turkey.fly()
    }
}

适配器TurkeyAdpater,持有turkey Turkey,实现Duck接口。

代理模式

uml:
https://design-patterns.readt...

image

代理模式中的成员构成:

  • Subject(主体)
  • Proxy (代理人)
  • RealSubject(实际的主体)
  • Client (请求者)

代理的目的是在目标对象方法的基础上作增强,这种增强的本质通常就是对目标对象的方法进行拦截和过滤。

golang版的代理模式如下:

Subject

type Git interface {
    Clone(url string) bool
}

RealSubject

type Github struct{}

func (p Github) Clone(url string) bool {
    if strings.HasPrefix(url, "https") {
        fmt.Println("clone from " + url)
        return true
    }

    fmt.Println("failed to clone from " + url)
    return false
}

Proxy

type GitBash struce {
    //将持有被代理主体
    GitCmd Git
}

func (p GitBash) Clone(url string) bool {
    //实际上是被代理主体在执行动作
    return p.GitCmd.Clone(url)
}

Client
此处client定义为一个coder

type Coder struct {}

func (p Coder) GetCode(url string) {
    gitBash := GetGit()

    if gitBash.Clone(url) {
        fmt.Println("success...")
    } else {
        fmt.Println("failed...")
    }
}

func main() {
    coder := Coder{}

    coder.GetCode("https://www.github.com")
}

装饰模式

uml
https://design-patterns.readt...

image

装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更为灵活。

装饰模式是代理模式的一种特殊应用,两者的共同点是都具有相同的接口,不同点则是代理模式着重为代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,它着重类的功能变化。

package main

import "fmt"

type Noddles interface {
    Description() string
    Price() float32
}

//普通拉面
type Ramen struct {
    name string
    price float32
}

func (p Ramen) Description() string {
    return p.name
}

func (p Ramen) Price() float32 {
    return p.price
}

//想吃鸡蛋拉面怎么办?
type Egg struct {
    //多用组合,少用继承,何况golang没有继承
    noddles Noddles
    name string
    price float32
}

func (p Egg) SetNoddles(noddles Noddles)  {
    p.noddles = noddles
}

func (p Egg) Description() string {
    return p.noddles.Description() + " + " + p.name
}

func (p Egg) Price() float32 {
    return p.noddles.Price() + p.price
}

//加个香肠吧!
type Sausage struct {
    noddles Noddles
    name string
    price float32
}

func (p Sausage) SetNoddles(noddles Noddles) {
    p.noddles = noddles
}

func (p Sausage) Description() string {
    return p.noddles.Description() + " + " + p.name
}

func (p Sausage) Price() float32 {
    return p.noddles.Price() + p.price
}

func main() {
    ramen := Ramen{
        name:"ramen",
        price:8,
    }

    egg := Egg{
        noddles:ramen,
        name:"egg",
        price:2,
    }

    egg2 := Egg{
        noddles:egg,
        name:"egg",
        price:2,
    }

    sausage := Sausage{
        noddles:egg,
        name:"sausage",
        price:2,
    }

    fmt.Println("客官,您的普通拉面来了。。。")
    fmt.Println(ramen.Description())
    fmt.Println(ramen.Price())

    fmt.Println("客官,您的鸡蛋拉面来了。。。")
    fmt.Println(egg.Description())
    fmt.Println(egg.Price())

    fmt.Println("客官,您的双蛋拉面来了。。。")
    fmt.Println(egg2.Description())
    fmt.Println(egg2.Price())

    fmt.Println(sausage.Description())
    fmt.Println(sausage.Price())
    fmt.Println("客官,您的香肠拉面来了。。。")

}

外观模式

外观模式也叫做门面模式,要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

uml图
https://design-patterns.readt...

image

image

一个服务有若干个子服务,这种情况下,可以引入一个统一的gateway层作为外观模式,统一管理入口。


image
package main

import "fmt"

type Facade struct {
    M Music
    V Video
    C Count
}

func (this *Facade) GetRecommandVideos() error {
    this.V.GetVideos()
    return nil
}

type Video struct {
    vid int64
}

func (this *Video) GetVideos() error {
    fmt.Println("get videos")
    return nil
}

type Music struct {
}

func (this *Music) GetMusic() error {
    fmt.Println("get music material")
    return nil
}

type Count struct {
    PraiseCnt int64
    CommentCnt int64
    CollectCnt int64
}

func (this *Count) GetCountById(id int64) (*Count, error) {
    fmt.Println("get video counts")
    return this, nil
}

func main() {
    f := &Facade{}
    f.GetRecommandVideos()
}

享元模式

image
package main

import (
    "fmt"
    "reflect"
)

type Coordinate struct {
    x, y int
}

type ChessFlyWeight interface {
    getColor() string
    display(c Coordinate)
}

type ConcreteChess struct {
    Color string
}

func (chess ConcreteChess) display(c Coordinate) {
    fmt.Printf("棋子颜色:%s\n", chess.Color)
    fmt.Printf("棋子位置:%d----%d\n", c.x, c.y)
}

func (chess ConcreteChess) getColor() string {
    return chess.Color
}

type ChessFlyWeightFactory struct {
    pool map[string]ChessFlyWeight
}

func (factory ChessFlyWeightFactory) getChess(color string) ChessFlyWeight {
    chess := factory.pool[color];

    if chess == nil {
        chess = ConcreteChess{color}
        factory.pool[color] = chess
    }

    return chess
}

func main() {
    pool  := make(map[string]ChessFlyWeight)

    factory := ChessFlyWeightFactory{pool   }

    chess1 := factory.getChess("black")
    chess2 := factory.getChess("black")

    fmt.Println(reflect.DeepEqual(chess1, chess2))
    c1 := Coordinate{1,2}
    c2 := Coordinate{2, 4}
    chess1.display(c1)
    chess1.display(c2)
}

桥梁模式

image
package main

import (
    "net/http"
    "fmt"
)

//请求接口
type Request interface {
    HttpRequest() (*http.Request, error)
}

type Client struct {
    Client *http.Client
}

func (c *Client) Query(req Request) (resp *http.Response, err error) {
    httpReq, _ := req.HttpRequest()
    resp, err = c.Client.Do(httpReq)
    return
}

//实现
type CdnRequest struct {
}

func (cdn *CdnRequest) HttpRequest() (*http.Request, error) {
    return http.NewRequest("GET", "/cdn", nil)
}

//实现2
type LiveRequest struct {
}

func (cdn *LiveRequest) HttpRequest() (*http.Request, error) {
    return http.NewRequest("GET", "/live", nil)
}

func TestBridge()  {
    client := &Client{http.DefaultClient}

    cdnReq := &CdnRequest{}
    fmt.Println(client.Query(cdnReq))

    liveReq := &LiveRequest{}
    fmt.Println(client.Query(liveReq))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348