# 设计模式
# 工厂模式
工厂模式(Factory Pattern)是软件设计中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。在每增加一种类型时,只需要修改工厂函数即可。 在产品较多时,工厂函数代码逻辑将会非常复杂。
type Restaurant interface {
GetFood()
}
type ChuanChuan struct {}
func (d *ChuanChuan) GetFood() {
fmt.Println("串串的饭菜已经做好")
}
type Qingfeng struct {}
func (q *Qingfeng) GetFood() {
fmt.Println("庆风包子铺已经做好")
}
func NewRestaurant(name string) Restaurant {
switch name {
case "d":
return &ChuanChuan{}
case "q":
return &Qingfeng{}
}
return nil
}
func main() {
// 工厂模式:首先要规定你生成的商品的功能是什么,如上的Restaurant接口就是要求商品都能获得食物
// 然后我们分别写能完成接口功能的结构体,然后通过NewRestaurant方法的select来通过不同的传参生产不同的商品
NewRestaurant("d").GetFood()
NewRestaurant("q").GetFood()
}
# 抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。 使用抽象工厂模式一般要满足以下条件。
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
- 系统一次只可能消费其中某一族产品,即同族的产品一起使用。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码,满足开闭原则
package main
import (
"fmt"
)
// lunch是表示一个具有cook功能的商品,下面的rise米饭和tomato番茄都实现了可以cook
type Lunch interface {
Cook()
}
type Rise struct {}
func (r *Rise) Cook() {
fmt.Println("it's rise")
}
type Tomato struct {}
func (t *Tomato) Cook() {
fmt.Println("it's Tomato")
}
type SimpleLunchFactory struct {}
// lunchFactory接口是表示具有createFood和Createvegetable功能的
type LunchFactory interface {
// 抽象工厂在此体现:接口内的方法会返回一个接口,这使得实现了LunchFactory的类与实现了Lunch功能的类进行绑定
CreateFood() Lunch
CreateVegetable() Lunch
}
func NewSimpleLunchFactory() LunchFactory {
return &SimpleLunchFactory{}
}
func (c *SimpleLunchFactory) CreateFood() Lunch {
return &Rise{}
}
func (c *SimpleLunchFactory) CreateVegetable() Lunch {
return &Tomato{}
}
func main() {
factory := NewSimpleLunchFactory()
food:= factory.CreateFood() // 通过LunchFactory的接口的方法来具体的创建不同的类
food.Cook()
vegetable := factory.CreateVegetable()
vegetable.Cook()
}
# 建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
import (
"bytes"
"fmt"
)
// builder设计模式,主要解决多变参数传递问题
// xorm就是使用了builder设计模式
// 故事: 平时去面馆吃面,有各种味道的面条(牛肉味、肥肠味等)
// 有各种配料(香菜、葱、姜、辣椒等)
// 第一个客人:一碗牛肉面 加葱、姜
// 第二个客人:一碗牛肉面 加葱、香菜
// 相当于面的材料
type MyBuilder struct {
NoodlesType string // 面条口味
Coriander bool // 是否加香菜
Onion bool // 是否加葱
Ginger bool // 是否加姜
Pepper bool // 是否加辣椒
}
// 构造一个结构体
func NewMyBuilder(noodsType string) MyBuilder {
return MyBuilder{NoodlesType: noodsType}
}
// 加香菜
func (myBuilder MyBuilder) withCoriander() MyBuilder {
myBuilder.Coriander = true
return myBuilder
}
// 加葱
func (myBuilder MyBuilder) withOnion() MyBuilder {
myBuilder.Onion = true
return myBuilder
}
// 加姜
func (myBuilder MyBuilder) withGinger() MyBuilder {
myBuilder.Ginger = true
return myBuilder
}
// 加辣椒
func (myBuilder MyBuilder) withPepper() MyBuilder {
myBuilder.Pepper = true
return myBuilder
}
func (myBuilder MyBuilder) String() string {
var buffer bytes.Buffer
buffer.WriteString("要一碗" + myBuilder.NoodlesType + "面,")
if myBuilder.Coriander {
buffer.WriteString("加香菜、")
} else {
buffer.WriteString("不加香菜、")
}
if myBuilder.Onion {
buffer.WriteString("加葱、")
} else {
buffer.WriteString("不加葱、")
}
if myBuilder.Ginger {
buffer.WriteString("加姜、")
} else {
buffer.WriteString("不加姜、")
}
if myBuilder.Pepper {
buffer.WriteString("加辣椒、")
} else {
buffer.WriteString("不加辣椒、")
}
buffer.WriteString("\n")
return buffer.String()
}
func main() {
myBuilder := NewMyBuilder("牛肉").
withCoriander().
withGinger()
str := myBuilder.String()
fmt.Println(str)
}
// 要一碗牛肉面,加香菜、不加葱、加姜、不加辣椒、
# 单例模式
单例模式(Singleton Pattern)是软件设计中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
package main
import (
"fmt"
"sync"
)
type Instance struct {
Name string
Counter int //详细参数
}
// 1、懒汉模式:非线程安全。,有线程来访问此时LazyInstance = nil就会再创建,单例类就会有多个实例了。当正在创建时
var LazyInstance *Instance
func GetLazyInstance() *Instance {
if LazyInstance == nil {
LazyInstance = &Instance{
Counter: 0,
Name: "LazyInstance",
}
}
return LazyInstance
}
// 改进型懒汉模式
var mu sync.Mutex
var LazyInsPlusPlus *Instance
func GetLazyInsPlusPlus() *Instance {
if LazyInsPlusPlus == nil {
mu.Lock()
defer mu.Unlock()
LazyInsPlusPlus = &Instance{
Counter: 0,
Name: "LazyInsPlusPlus",
}
}
return LazyInsPlusPlus
}
// sync.once实现
var once sync.Once
var SyncOnceInstance *Instance
func GetInstanceSyncOnce() *Instance {
once.Do(func() {
SyncOnceInstance = &Instance{
Counter: 0,
Name: "SyncOnceInstance",
}
})
return SyncOnceInstance
}
func (i *Instance) Hello() {
fmt.Printf("%s: my current counter is:%d\n", i.Name, i.Counter)
}
//省略实现
func main() {
//懒汉模式测试
ls := GetLazyInstance()
ls.Hello()
ls.Counter += 1
ls1 := GetLazyInstance()
ls1.Hello()
//饿汉模式测试
lspp := GetLazyInsPlusPlus()
lspp.Hello()
lspp.Counter += 1000
lspp1 := GetLazyInsPlusPlus()
lspp1.Hello()
//sync once 测试
sc := GetInstanceSyncOnce()
sc.Hello()
sc.Counter += 10000
sc1 := GetInstanceSyncOnce()
sc1.Hello()
}
/*
LazyInstance: my current counter is:0
LazyInstance: my current counter is:1
LazyInsPlusPlus: my current counter is:0
LazyInsPlusPlus: my current counter is:1000
SyncOnceInstance: my current counter is:0
SyncOnceInstance: my current counter is:10000
*/
# 创建型模式
# 原型模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
type Cloneable interface {
Clone() Cloneable
}
type Person struct {
Name string
Age int
Height int
}
func (p *Person) Clone() *Person {
person := *p
return &person
}
func(p *Person) SetName(name string) {
p.Name = name
}
func(p *Person) SetAge(age int) {
p.Age = age
}
func main() {
p := &Person{
Name: "zhang san",
Age: 20,
Height: 175,
}
p1 :=p.Clone()
p1.SetAge(30)
p1.SetName("Li Si")
fmt.Println("name:", p1.Name)
fmt.Println("age:", p1.Age)
fmt.Println("height:", p1.Height)
}
/*
name: Li Si
age: 30
height: 175
*/
# 适配器模式
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。例如: 在现实生活中,我们的笔记本电脑的工作电压大多数都是20V,而我国的家庭用电是220V,如何让20V的笔记本电脑能够工作在220V的电压下工作?答案:引入一个电源适配器,俗称变压器,有了这个电源适配器,生活用电和笔记本电脑即可兼容。
// 将一个类的接口转换成客户希望的另一个接口,Adapter模式使得原本由于接口
// 不兼容而不能一起工作的那些类可以一起工作
// 定义一个新的接口
type Target interface {
Process()
}
// 定义一个老的接口
type Adaptee interface {
Foo()
Bar()
}
// 定一个Adapter接口
type Adapter struct {
adaptee Adaptee
}
func (a *Adapter) Process(){
fmt.Println("在Adapter中执行process()") // 在之前的基础上执行原有process函数
a.adaptee.Bar()
a.adaptee.Foo()
}
// 实现旧接口struct
type oldAdaptee struct {}
func (o *oldAdaptee) Foo(){
fmt.Println("在旧接口中执行foo()")
}
func (o *oldAdaptee) Bar(){
fmt.Println("在旧的接口中执行bar()")
}
func main(){
oa := new(oldAdaptee)
// 定一个适配器对象
adapter := new(Adapter)
adapter.adaptee = oa
adapter.Process()
}
# 结构设计模式
# 代理模式
代理设计模式是一种结构设计模式。这种模式建议为控制和访问主要对象提供额外的间接层。
在这种模式下,将创建一个新的代理类,该类实现与主对象相同的接口。这使您可以在主对象的实际逻辑之前或者之后执行某些行为。
package main
import "fmt"
type server interface {
handleRequest(string, string) (int, string)
}
type nginx struct {
application *application
maxAllowedRequest int
rateLimiter map[string]int
}
func newNginxServer() *nginx {
return &nginx{
application: &application{},
maxAllowedRequest: 2,
rateLimiter: make(map[string]int),
}
}
func (n *nginx) handleRequest(url, method string) (int, string) {
allowed := n.checkRateLimiting(url)
if !allowed {
return 403, "Not Allowed"
}
return n.application.handleRequest(url, method)
}
func (n *nginx) checkRateLimiting(url string) bool {
if n.rateLimiter[url] == 0 {
n.rateLimiter[url] = 1
}
if n.rateLimiter[url] > n.maxAllowedRequest {
return false
}
n.rateLimiter[url] = n.rateLimiter[url] + 1
return true
}
type application struct {
}
func (a *application) handleRequest(url, method string) (int, string) {
if url == "/app/status" && method == "GET" {
return 200, "Ok"
}
if url == "/create/user" && method == "POST" {
return 201, "User Created"
}
return 404, "Not Ok"
}
func main() {
nginxServer := newNginxServer()
appStatusURL := "/app/status"
createuserURL := "/create/user"
httpCode, body := nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(createuserURL, "POST")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", createuserURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(createuserURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", createuserURL, httpCode, body)
}
/*
Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 403
Body: Not Allowed
Url: /create/user
HttpCode: 201
Body: User Created
Url: /create/user
HttpCode: 404
Body: Not Ok
*/
← Go下载大文件io.Copy 微服务网关 →