├── README.md ├── behavioral_patterns ├── README.md └── observer.go ├── creational_patterns ├── README.md ├── builder.go ├── funcfactory.go ├── simplefactory.go ├── singleton.go └── singleton_simple.go └── structural_patterns ├── README.md ├── decorator.go ├── facade.go └── proxy.go /README.md: -------------------------------------------------------------------------------- 1 | # 1. 简述 2 | ------------------- 3 | 在面向对象的编程语言中(如java,C++)设计模式的概念广为人知, 应用的也非常广泛。设计模式让我们的代码变得灵活起来,具有很强的扩展性。但在与C语言比肩的Go语言中,设计模式的概念并没有十分突出,甚至很少听到。在Go的开发中,借鉴design pattern的理念同样回味无穷我们的开发带来极大的便利。 4 | 5 | ![go-logo](http://img.blog.csdn.net/20170826191635943) 6 | 7 | # 2. Design pattern in go 学习实践 8 | ------------------- 9 | 老生常谈,还是从设计模式的三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)开始介绍。 10 | 11 | ## 2.1 创建型模式 12 | 创建型设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 13 | 14 | |模式|描述| 15 | |:--:|:--:| 16 | |[简单工厂模式](https://github.com/jeanphorn/go-design-patterns/blob/master/creational_patterns/simplefactory.go)|提供一个接口,根据不同的输入生成不同的实例| 17 | |[工厂方法模式](https://github.com/jeanphorn/go-design-patterns/blob/master/creational_patterns/funcfactory.go)|每个实例都有创建该实例的工厂| 18 | |[建造者模式](https://github.com/jeanphorn/go-design-patterns/blob/master/creational_patterns/builder.go)|将一个复杂的对象与它的表示分离,同样的创造过程可以建造出不停的表示| 19 | |[单例模式](https://github.com/jeanphorn/go-design-patterns/blob/master/creational_patterns/singleton.go)|在程序运行过程中之产生一个实例| 20 | 21 | ## 2.2 结构型模式 22 | 23 | 结构型模式是将对象或结构体通过一定方式组成一个更复杂的对象或结构体,使其具有更复杂的功能,就像搭积木一样。结构型的模式同通常包括外观模式,桥接模式,适配器模式,装饰模式等。 24 | 25 | |模式|描述| 26 | |:--:|:--:| 27 | |[外观模](https://github.com/jeanphorn/go-design-patterns/blob/master/structural_patterns/facade.go)|引入子系统统一调用入口| 28 | |[装饰模式](https://github.com/jeanphorn/go-design-patterns/blob/master/structural_patterns/decorator.go)|动态扩展已存在对象的功能| 29 | |[代理模式](https://github.com/jeanphorn/go-design-patterns/blob/master/structural_patterns/proxy.go)|通过一个对象代理其他对象的功能| 30 | 31 | ## 2.2 行为型模式 32 | 33 | 行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。 34 | 35 | |模式|描述| 36 | |:--:|:--:| 37 | |[观察者模式](https://github.com/jeanphorn/go-design-patterns/blob/master/behavioral_patterns/observer.go)|将特定事件发生引起关联的观察者对象更新相关内容| 38 | -------------------------------------------------------------------------------- /behavioral_patterns/README.md: -------------------------------------------------------------------------------- 1 | ## 观察者模式 2 | 3 | ### 概述 4 | 5 | 观察者模式简单一句话说就是当特定事件出现时,一个对象实例把事件发布到对应的观察者实例上执行相应的更新操作。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。 6 | 7 | 其类图如下: 8 | 9 | ![](https://dzone.com/storage/temp/887275-classic-observer-pattern-class-diagram.jpg) 10 | 11 | ### golang具体实现示例 12 | 13 | 1. 首先,定一个事件类型,发生事件驱动时将事件传递给观察者们。这里数据是一个string类型的data, 实际情况可更具需要而定。 14 | 15 | ``` 16 | type Event struct { 17 | Data string 18 | } 19 | ``` 20 | 21 | 2. 定义观察者和观察对象的接口。Observer定义了一个更新发生事件的标准接口,Subject是具体被观察的接口,他有注册观察者、注销观察者和发布通知的三个主要函数接口。 22 | 23 | ``` 24 | type Observer interface { 25 | //更新事件 26 | Update(*Event) 27 | } 28 | 29 | // 被观察的对象接口 30 | type Subject interface { 31 | //注册观察者 32 | Regist(Observer) 33 | //注销观察者 34 | Deregist(Observer) 35 | 36 | //通知观察者事件 37 | Notify(*Event) 38 | } 39 | 40 | ``` 41 | 42 | 3. 实现观察者和对象的接口。 43 | 44 | ``` 45 | type ConcreteObserver struct { 46 | Id int 47 | } 48 | 49 | func (co *ConcreteObserver) Update(e *Event) { 50 | fmt.Printf("observer [%d] recieved msg: %s.\n", co.Id, e.Data) 51 | } 52 | 53 | type ConcreteSubject struct { 54 | Observers map[Observer]struct{} 55 | } 56 | 57 | func (cs *ConcreteSubject) Regist(ob Observer) { 58 | cs.Observers[ob] = struct{}{} 59 | } 60 | 61 | func (cs *ConcreteSubject) Deregist(ob Observer) { 62 | delete(cs.Observers, ob) 63 | } 64 | 65 | // 通知每个观察者事件 66 | func (cs *ConcreteSubject) Notify(e *Event) { 67 | for ob, _ := range cs.Observers { 68 | ob.Update(e) 69 | } 70 | } 71 | 72 | ``` 73 | 74 | ### 使用 75 | 76 | ``` 77 | func main() { 78 | cs := &ConcreteSubject{ 79 | Observers: make(map[Observer]struct{}), 80 | } 81 | 82 | //实例化两个观察者 83 | cobserver1 := &ConcreteObserver{1} 84 | cobserver2 := &ConcreteObserver{2} 85 | 86 | //注册观察者 87 | cs.Regist(cobserver1) 88 | cs.Regist(cobserver2) 89 | 90 | for i := 0; i < 5; i++ { 91 | e := &Event{fmt.Sprintf("msg [%d]", i)} 92 | cs.Notify(e) 93 | 94 | time.Sleep(time.Duration(1) * time.Second) 95 | } 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /behavioral_patterns/observer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type Event struct { 9 | Data string 10 | } 11 | 12 | type Observer interface { 13 | //更新事件 14 | Update(*Event) 15 | } 16 | 17 | // 被观察的对象接口 18 | type Subject interface { 19 | //注册观察者 20 | Regist(Observer) 21 | //注销观察者 22 | Deregist(Observer) 23 | 24 | //通知观察者事件 25 | Notify(*Event) 26 | } 27 | 28 | type ConcreteObserver struct { 29 | Id int 30 | } 31 | 32 | func (co *ConcreteObserver) Update(e *Event) { 33 | fmt.Printf("observer [%d] recieved msg: %s.\n", co.Id, e.Data) 34 | } 35 | 36 | type ConcreteSubject struct { 37 | Observers map[Observer]struct{} 38 | } 39 | 40 | func (cs *ConcreteSubject) Regist(ob Observer) { 41 | cs.Observers[ob] = struct{}{} 42 | } 43 | 44 | func (cs *ConcreteSubject) Deregist(ob Observer) { 45 | delete(cs.Observers, ob) 46 | } 47 | 48 | func (cs *ConcreteSubject) Notify(e *Event) { 49 | for ob, _ := range cs.Observers { 50 | ob.Update(e) 51 | } 52 | } 53 | 54 | func main() { 55 | cs := &ConcreteSubject{ 56 | Observers: make(map[Observer]struct{}), 57 | } 58 | 59 | cobserver1 := &ConcreteObserver{1} 60 | cobserver2 := &ConcreteObserver{2} 61 | 62 | cs.Regist(cobserver1) 63 | cs.Regist(cobserver2) 64 | 65 | for i := 0; i < 5; i++ { 66 | e := &Event{fmt.Sprintf("msg [%d]", i)} 67 | cs.Notify(e) 68 | 69 | time.Sleep(time.Duration(1) * time.Second) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /creational_patterns/README.md: -------------------------------------------------------------------------------- 1 | ## 1. 简单工厂模式 2 | 3 | 类图: 4 | ![](http://img.blog.csdn.net/20170826202731964) 5 | 6 | 和传统的Java等面向对象语言的继承机制不同,在Go语言中并不提倡使用继承,但是在某些场景下要用到继承的话,可以用下面的方式实现继承关系。 7 | 8 | ``` 9 | type Animal struct { 10 | Category string 11 | } 12 | 13 | type Dog struct { 14 | Animal 15 | Name string 16 | } 17 | ``` 18 | 简单工厂模式实现起来也比较简单,主要代码如下: 19 | 20 | ``` 21 | type AnimalFactory struct { 22 | } 23 | 24 | func NewAnimalFactory() *AnimalFactory { 25 | return &AnimalFactory{} 26 | } 27 | 28 | func (this *AnimalFactory) CreateAnimal(name string) Action { 29 | switch name { 30 | case "bird": 31 | return &Bird{} 32 | case "fish": 33 | return &Fish{} 34 | case "dog": 35 | return &Dog{} 36 | default: 37 | panic("error animal type") 38 | return nil 39 | } 40 | } 41 | ``` 42 | 43 | ## 2. 工厂方法模式 44 | 45 | 简单工厂模式是通过传递不同的参数生成不同的实例,缺点就是扩展不同的类别时需要修改代码。 46 | 47 | 工厂方法模式为每一个product提供一个工程类,通过不同工厂创建不同实例。 48 | 49 | 类图: 50 | 51 | ![func](http://p0.qhimg.com/t0136c0b7b213d65023.gif) 52 | 53 | 实现过程: 54 | 55 | - 1. 工厂方法定义一个创建struct的接口,让子struct去实现。 56 | 57 | ``` 58 | type AnimalFactory interface { 59 | CreateAnimal() Action 60 | } 61 | 62 | ``` 63 | 64 | - 2. BirdFactory创建一个Bird的实例 65 | 66 | ``` 67 | type BirdFactory struct { 68 | } 69 | 70 | func (this *BirdFactory) CreateAnimal() Action { 71 | return &Bird{} 72 | } 73 | 74 | ``` 75 | 76 | - 3. 工厂方法使用 77 | 78 | ``` 79 | bFactory := &BirdFactory{} 80 | bird := bFactory.CreateAnimal() 81 | bird.Move(100) 82 | 83 | ``` 84 | 85 | ### 3. 建造者模式 86 | 87 | 建造者模式将一个复杂的对象与它的表示分离,同样的创造过程可以建造出不停的表示。比如汽车,它包括商标、车轮、颜色、发送机等各种部分。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。 88 | 89 | 类图: 90 | ![builder](http://img.blog.csdn.net/20170903163110850) 91 | 92 | Go语言实现: 93 | 94 | ``` 95 | package main 96 | 97 | import ( 98 | "fmt" 99 | ) 100 | 101 | //产品角色 102 | type Car struct { 103 | Brand string 104 | Type string 105 | Color string 106 | } 107 | 108 | func (this *Car) Drive() error { 109 | fmt.Printf("A %s %s %s car is running on the road!\n", this.Color, this.Type, this.Brand) 110 | return nil 111 | } 112 | 113 | //建造者角色 114 | type Builder interface { 115 | PaintColor(color string) Builder 116 | AddBrand(brand string) Builder 117 | SetType(t string) Builder 118 | Build() Car 119 | } 120 | 121 | //具体的建造者 122 | type ConcreteBuilder struct { 123 | ACar Car 124 | } 125 | 126 | func (this *ConcreteBuilder) PaintColor(cor string) Builder { 127 | this.ACar.Color = cor 128 | return this 129 | } 130 | 131 | func (this *ConcreteBuilder) AddBrand(bnd string) Builder { 132 | this.ACar.Brand = bnd 133 | return this 134 | } 135 | 136 | func (this *ConcreteBuilder) SetType(t string) Builder { 137 | this.ACar.Type = t 138 | return this 139 | } 140 | 141 | func (this *ConcreteBuilder) Build() Car { 142 | return this.ACar 143 | } 144 | 145 | //导演着角色 146 | type Director struct { 147 | Builder Builder 148 | } 149 | 150 | func main() { 151 | dr := Director{&ConcreteBuilder{}} 152 | adCar := dr.Builder.SetType("SUV").AddBrand("奥迪").PaintColor("white").Build() 153 | adCar.Drive() 154 | 155 | bwCar := dr.Builder.SetType("sporting").AddBrand("宝马").PaintColor("red").Build() 156 | bwCar.Drive() 157 | 158 | } 159 | ``` 160 | 161 | ## 4. 单例模式 162 | 163 | 单例模式,顾名思义就是在程序的运行中只产生一个实力。在Go实现上也有多种形式。 164 | 165 | 1. 懒汉模式. 166 | 这种方式实现起来特别简单,直接判断一个实力是不是为`nil`, 如果是,则新生成;否则返回已有的。但它和多数语言一样,只适合用在单线程。 167 | 168 | ``` 169 | type SingleTon struct { 170 | } 171 | 172 | var instance *SingleTon 173 | 174 | func GetInstance() *SingleTon { 175 | if Instance == nil { 176 | instance = &SingleTon{} 177 | } 178 | 179 | return instance 180 | } 181 | ``` 182 | 183 | 2. 使用加锁机制 184 | 185 | 在Go语言中有个基础对象`sync.Mutex`,可以实现协程之间的同步逻辑。 186 | 187 | ``` 188 | var mu sync.Mutex 189 | 190 | func GetInstance() *SingleTon { 191 | mu.Lock() 192 | defer mu.Unock() 193 | 194 | if Instance == nil { 195 | instance = &SingleTon{} 196 | } 197 | 198 | return instance 199 | } 200 | ``` 201 | 202 | 3. `sync.Once`用法 203 | 204 | 在Go中还有一个更简洁的方法就是使用`sync.Once`,它可以在多协程中起到控制作用。实现起来也非常简单。 205 | 206 | ``` 207 | var ( 208 | once sync.Once 209 | instance *SingleTon 210 | ) 211 | 212 | func GetInstance(str string) *SingleTon { 213 | once.Do(func() { 214 | instance = &SingleTon{Attr: str} 215 | }) 216 | 217 | return instance 218 | } 219 | ``` 220 | 测试代码如下,从运行结果来看,都是一致的。 221 | 222 | ``` 223 | func main() { 224 | for i := 0; i < 10; i++ { 225 | go func() { 226 | s := GetInstance("test:" + strconv.Itoa(i)) 227 | s.TestFunc() 228 | }() 229 | } 230 | time.Sleep(1e5) 231 | } 232 | 233 | ``` 234 | -------------------------------------------------------------------------------- /creational_patterns/builder.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //产品角色 8 | type Car struct { 9 | Brand string 10 | Type string 11 | Color string 12 | } 13 | 14 | func (this *Car) Drive() error { 15 | fmt.Printf("A %s %s %s car is running on the road!\n", this.Color, this.Type, this.Brand) 16 | return nil 17 | } 18 | 19 | //建造者角色 20 | type Builder interface { 21 | PaintColor(color string) Builder 22 | AddBrand(brand string) Builder 23 | SetType(t string) Builder 24 | Build() Car 25 | } 26 | 27 | //具体的建造者 28 | type ConcreteBuilder struct { 29 | ACar Car 30 | } 31 | 32 | func (this *ConcreteBuilder) PaintColor(cor string) Builder { 33 | this.ACar.Color = cor 34 | return this 35 | } 36 | 37 | func (this *ConcreteBuilder) AddBrand(bnd string) Builder { 38 | this.ACar.Brand = bnd 39 | return this 40 | } 41 | 42 | func (this *ConcreteBuilder) SetType(t string) Builder { 43 | this.ACar.Type = t 44 | return this 45 | } 46 | 47 | func (this *ConcreteBuilder) Build() Car { 48 | return this.ACar 49 | } 50 | 51 | //导演着角色 52 | type Director struct { 53 | Builder Builder 54 | } 55 | 56 | func main() { 57 | dr := Director{&ConcreteBuilder{}} 58 | adCar := dr.Builder.SetType("SUV").AddBrand("奥迪").PaintColor("white").Build() 59 | adCar.Drive() 60 | 61 | bwCar := dr.Builder.SetType("sporting").AddBrand("宝马").PaintColor("red").Build() 62 | bwCar.Drive() 63 | 64 | } 65 | -------------------------------------------------------------------------------- /creational_patterns/funcfactory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Action interface { 8 | Move(int) int 9 | } 10 | 11 | type Animal struct { 12 | Name string 13 | } 14 | 15 | type Bird struct { 16 | Animal 17 | } 18 | 19 | func (this *Bird) Move(num int) int { 20 | fmt.Printf("I am a bird, I flyed %d meters.\n", num) 21 | return num 22 | } 23 | 24 | type Fish struct { 25 | Animal 26 | } 27 | 28 | func (this *Fish) Move(num int) int { 29 | fmt.Printf("I am a fish, I swimmed %d meters.\n", num) 30 | return num 31 | } 32 | 33 | type AnimalFactory interface { 34 | CreateAnimal() Action 35 | } 36 | 37 | type BirdFactory struct { 38 | } 39 | 40 | func (this *BirdFactory) CreateAnimal() Action { 41 | return &Bird{} 42 | } 43 | 44 | type FishFactory struct { 45 | } 46 | 47 | func (this *FishFactory) CreateAnimal() Action { 48 | return &Fish{} 49 | } 50 | 51 | func main() { 52 | bFactory := &BirdFactory{} 53 | bird := bFactory.CreateAnimal() 54 | bird.Move(100) 55 | 56 | fFactory := &FishFactory{} 57 | fish := fFactory.CreateAnimal() 58 | fish.Move(200) 59 | 60 | } 61 | -------------------------------------------------------------------------------- /creational_patterns/simplefactory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Action interface { 8 | Move(int) int 9 | } 10 | 11 | type Animal struct { 12 | Name string 13 | } 14 | 15 | type Bird struct { 16 | Animal 17 | } 18 | 19 | func (this *Bird) Move(num int) int { 20 | fmt.Printf("I am a bird, I flyed %d meters.\n", num) 21 | return num 22 | } 23 | 24 | type Fish struct { 25 | Animal 26 | } 27 | 28 | func (this *Fish) Move(num int) int { 29 | fmt.Printf("I am a fish, I swimmed %d meters.\n", num) 30 | return num 31 | } 32 | 33 | type Dog struct { 34 | Animal 35 | } 36 | 37 | func (this *Dog) Move(num int) int { 38 | fmt.Printf("I am a dog, I flying %d meters.\n", num) 39 | return num 40 | } 41 | 42 | type AnimalFactory struct { 43 | } 44 | 45 | func NewAnimalFactory() *AnimalFactory { 46 | return &AnimalFactory{} 47 | } 48 | 49 | func (this *AnimalFactory) CreateAnimal(name string) Action { 50 | switch name { 51 | case "bird": 52 | return &Bird{} 53 | case "fish": 54 | return &Fish{} 55 | case "dog": 56 | return &Dog{} 57 | default: 58 | panic("error animal type") 59 | return nil 60 | } 61 | } 62 | 63 | func main() { 64 | bird := NewAnimalFactory().CreateAnimal("bird") 65 | bird.Move(100) 66 | 67 | fish := NewAnimalFactory().CreateAnimal("fish") 68 | fish.Move(200) 69 | 70 | dog := NewAnimalFactory().CreateAnimal("dog") 71 | dog.Move(300) 72 | } 73 | -------------------------------------------------------------------------------- /creational_patterns/singleton.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | type Instance interface { 11 | TestFunc() 12 | } 13 | 14 | type SingleTon struct { 15 | Attr string 16 | } 17 | 18 | func (this *SingleTon) TestFunc() { 19 | fmt.Println(this.Attr) 20 | } 21 | 22 | var ( 23 | once sync.Once 24 | instance *SingleTon 25 | ) 26 | 27 | func GetInstance(str string) *SingleTon { 28 | once.Do(func() { 29 | instance = &SingleTon{Attr: str} 30 | }) 31 | 32 | return instance 33 | } 34 | 35 | func main() { 36 | for i := 0; i < 10; i++ { 37 | go func() { 38 | s := GetInstance("test:" + strconv.Itoa(i)) 39 | s.TestFunc() 40 | }() 41 | } 42 | time.Sleep(1e5) 43 | } 44 | -------------------------------------------------------------------------------- /creational_patterns/singleton_simple.go: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * 4 | */ 5 | 6 | package singleton 7 | 8 | type SingleTon struct { 9 | } 10 | 11 | var instance *SingleTon 12 | 13 | func GetInstance() *SingleTon { 14 | if Instance == nil { 15 | instance = &SingleTon{} 16 | } 17 | 18 | return instance 19 | } 20 | -------------------------------------------------------------------------------- /structural_patterns/README.md: -------------------------------------------------------------------------------- 1 | ## 结构型模式(structural pattern) 2 | 3 | 结构型模式是将对象或结构体通过一定方式组成一个更复杂的对象或结构体,使其具有更复杂的功能,就像搭积木一样。结构型的模式同通常包括外观模式,桥接模式,适配器模式,装饰模式等。 4 | 5 | ### 1. 外观模式 6 | 7 | 它为一套复杂的调度子系统提供一个统一的接入接口。外部所有对子系统的调用都通过这个外观角色进行统一调用,降低子系统与调用者之间的耦合度。 8 | 9 | 那当前比较热门的微服务来说,一套服务(比如说短视频服务)包括若干子服务,如图(a),如:音乐服务,短视频服务,计数服务,推荐子服务等。客户端不同的请求会使用不同的子服务。客户端视频创作会请求音乐素材,视频上传服务;浏览推荐视频需要请求视频推荐服务和计数服务。这种情况下,我们可以引入一个统一的gateway层作为外观模式,统一管理入口, 如图(b)。 10 | 11 | ![before](http://img.blog.csdn.net/20170924155726971) 12 | 13 | **图(a)** 14 | 15 | ![after](http://img.blog.csdn.net/20170924155738037) 16 | 17 | **图(b)** 18 | 19 | 外观模式类图: 20 | 21 | ![](https://www.packtpub.com/sites/default/files/Article-Images/B05180_01.png) 22 | 23 | Go语言实现: 24 | 25 | ``` 26 | type Facade struct { 27 | M Music 28 | V Video 29 | C Count 30 | } 31 | 32 | func (this *Facade) GetRecommandVideos() error { 33 | this.V.GetVideos() 34 | this.C.GetCountByID(111) 35 | 36 | return nil 37 | } 38 | 39 | type Music struct { 40 | } 41 | 42 | func (this *Music) GetMusic() error { 43 | fmt.Println("get music material") 44 | // logic code here 45 | return nil 46 | } 47 | 48 | type Video struct { 49 | vid int64 50 | } 51 | 52 | func (this *Video) GetVideos() error { 53 | fmt.Println("get videos1") 54 | return nil 55 | } 56 | 57 | type Count struct { 58 | PraiseCnt int64 //点赞数 59 | CommentCnt int64 //评论数 60 | CollectCnt int64 //收藏数 61 | } 62 | 63 | func (this *Count) GetCountByID(id int64) (*Count, error) { 64 | fmt.Println("get video counts") 65 | return this, nil 66 | } 67 | 68 | ``` 69 | 70 | ### 2. 装饰模式 71 | 72 | 装饰模式就是在不改变对象内部结构的情况下,动态扩展它的功能。它提供了灵活的方法来扩展对象的功能。 73 | 74 | 75 | 下面是一个简单的实现逻辑,通过Decorate来进一步装饰`Dressing`函数: 76 | 77 | ``` 78 | type Object func(string) string 79 | 80 | func Decorate(fn Object) Object { 81 | return func(base string) string { 82 | 83 | ret := fn(base) 84 | 85 | ret = ret + " and Tshirt" 86 | return ret 87 | } 88 | } 89 | 90 | func Dressing(cloth string) string { 91 | return "dressing " + cloth 92 | } 93 | 94 | ``` 95 | 96 | - 使用方式 97 | 98 | ``` 99 | f := Decorate(Dressing) 100 | fmt.Println(f("shoes")) 101 | ``` 102 | 103 | ### 3. 代理模式 104 | 105 | 代理模式,简单来说就是提供一个对象来控制其他对象的功能。在一些情况下,一个Object不适合直接引用目标对象,但可以通过代理对象调用目标对象,起到中介代理的作用。 106 | 107 | 108 | - 实现示例 109 | 110 | ``` 111 | //被代理的公共函数 112 | // 113 | type ProxyFuncs interface { 114 | //卖房功能 115 | SailHouse() 116 | } 117 | 118 | type MasterBeijing struct { 119 | Name string //北京业主姓名 120 | Location string //业主所卖房屋的位置 121 | } 122 | 123 | func (this *MasterBeijing) SailHouse() { 124 | fmt.Printf("%s sailing house at %s\n", this.Name, this.Location) 125 | } 126 | 127 | type Proxier struct { 128 | Mofbj *MasterBeijing 129 | } 130 | 131 | func (this *Proxier) SailHouse() { 132 | if this.Mofbj == nil { 133 | this.Mofbj = &MasterBeijing{} 134 | } 135 | 136 | this.Mofbj.SailHouse() 137 | } 138 | ``` 139 | -------------------------------------------------------------------------------- /structural_patterns/decorator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Object func(string) string 6 | 7 | func Decorate(fn Object) Object { 8 | return func(base string) string { 9 | 10 | ret := fn(base) 11 | 12 | ret = ret + " and Tshirt" 13 | return ret 14 | } 15 | } 16 | 17 | func Dressing(cloth string) string { 18 | return "dressing " + cloth 19 | } 20 | 21 | func main() { 22 | f := Decorate(Dressing) 23 | 24 | fmt.Println(f("shoes")) 25 | } 26 | -------------------------------------------------------------------------------- /structural_patterns/facade.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Facade struct { 8 | M Music 9 | V Video 10 | C Count 11 | } 12 | 13 | func (this *Facade) GetRecommandVideos() error { 14 | this.V.GetVideos() 15 | this.C.GetCountByID(111) 16 | 17 | return nil 18 | } 19 | 20 | type Music struct { 21 | } 22 | 23 | func (this *Music) GetMusic() error { 24 | fmt.Println("get music material") 25 | // logic code here 26 | return nil 27 | } 28 | 29 | type Video struct { 30 | vid int64 31 | } 32 | 33 | func (this *Video) GetVideos() error { 34 | fmt.Println("get videos1") 35 | return nil 36 | } 37 | 38 | type Count struct { 39 | PraiseCnt int64 //点赞数 40 | CommentCnt int64 //评论数 41 | CollectCnt int64 //收藏数 42 | } 43 | 44 | func (this *Count) GetCountByID(id int64) (*Count, error) { 45 | fmt.Println("get video counts") 46 | return this, nil 47 | } 48 | 49 | func main() { 50 | f := &Facade{} 51 | f.GetRecommandVideos() 52 | } 53 | -------------------------------------------------------------------------------- /structural_patterns/proxy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //被代理的公共函数 8 | // 9 | type ProxyFuncs interface { 10 | //卖房功能 11 | SailHouse() 12 | } 13 | 14 | type MasterBeijing struct { 15 | Name string //北京业主姓名 16 | Location string //业主所卖房屋的位置 17 | } 18 | 19 | func (this *MasterBeijing) SailHouse() { 20 | fmt.Printf("%s sailing house at %s\n", this.Name, this.Location) 21 | } 22 | 23 | type Proxier struct { 24 | Mofbj *MasterBeijing 25 | } 26 | 27 | func (this *Proxier) SailHouse() { 28 | if this.Mofbj == nil { 29 | this.Mofbj = &MasterBeijing{} 30 | } 31 | 32 | this.Mofbj.SailHouse() 33 | } 34 | 35 | func main() { 36 | m := &MasterBeijing{ 37 | Name: "Lao wang", 38 | Location: "Xi Cheng", 39 | } 40 | 41 | proxier := &Proxier{ 42 | Mofbj: m, 43 | } 44 | 45 | proxier.SailHouse() 46 | } 47 | --------------------------------------------------------------------------------