大家好,我是追麾(hui)。最近比较久没更新原创了,主要是工作上确实太忙。
这是Go的设计模式第五篇,这篇主要分享装饰器模式,门面模式,亨元模式。下面我们来看具体模式。
业界装饰器模式定义:指在不改变现有对象结构的情况下,向目标对象中动态地添加或删除功能。
装饰器模式优缺点
装饰器模式的应用场景
Go装饰器模式实现方式
装饰器模式主要包含以下主要角色。
装饰器模式基于原有的功能做一些增强,下面我们来看一下通过枪的例子来演示一下。
package main
import "fmt"
func main() {
m := MachineGun{}
m.Shooting()
s := SniperRifleGun{}
s.Shooting()
}
// 抽象构件
type DecorateGunInterface interface {
Shooting()
}
// 具体构件, 枪射击
type Gun struct {
}
func (g *Gun) Shooting() {
fmt.Println("枪射击")
}
// 抽象装饰角色, 这里是目标对象添加功能
type MachineDecorator struct {
Machine Gun
}
// 具体装饰,机关枪
type MachineGun struct {
Gun MachineDecorator
}
func (m *MachineGun) Shooting() {
fmt.Println("机关")
m.Gun.Machine.Shooting()
}
// 具体装饰,狙击枪
type SniperRifleGun struct {
Gun MachineDecorator
}
func (m *SniperRifleGun) Shooting() {
fmt.Println("狙击")
m.Gun.Machine.Shooting()
}
执行结果如下:
机关
枪射击
狙击
枪射击
业界门面模式定义:门面模式又叫外观模式,通过为多个复杂的子系统提供一个一致的统一的接口,而使这些子系统更加容易被访问的模式叫门面模式。
门面模式优缺点
门面模式的应用场景
Go门面模式实现方式
门面模式主要由以下角色:
下面我们通过一个电商的详情页面的例子来看下门面模式的实现。不同的子系统接口,通过一个门面接口进行整合统一,提供对外服务。
package main
import "fmt"
// 客户角色
func main() {
GetFacadeDetail()
}
type Product struct {
}
// 子系统角色A
func (p *Product) GetProductInfo() {
fmt.Println("这里是获取商品详情的信息接口")
}
type Stock struct {
}
// 子系统角色B
func (s *Stock) GetStockInfo() {
fmt.Println("这里是获取库存信息接口")
}
type Ad struct {
}
// 子系统角色C
func (a *Ad) GetAdInfo() {
fmt.Println("这里是获取广告营销的信息接口")
}
// 外观角色
func GetFacadeDetail() {
p := Product{}
a := Ad{}
s := Stock{}
p.GetProductInfo()
a.GetAdInfo()
s.GetStockInfo()
fmt.Println("详情页面所哟的接口...")
}
业界亨元模式定义:通过共享的方式提供数量庞大的细粒度对象的复用,通过共享能减少创建的数据对象,避免大量相似类的开销,从而提供系统资源的利用率。享元模式其实是工厂方法模式的一个改进机制。
亨元模式优缺点
亨元模式的应用场景
Go亨元模式实现方式
享元模式的主要角色:
下面我们来看一下例子,我们把枪当成一个具体亨元角色,写一个亨元工厂进行存储亨元角色数据。下面我们来看具体例子。
package main
import (
"fmt"
"sync"
)
func main() {
// 创建亨元
f := NewFlyWeightPattern()
// 具体亨元角色
b := NewGunBase()
f.SetElement("a1", b)
// 读取亨元数据
p := f.GetElement("a1").(GunProperty)
fmt.Println(p.Shoot())
// 非享元角色
b2 := NewSubMachineGun(b, "auto")
f.SetElement("b1", b2)
// 读取享元角色数据
p2 := f.GetElement("b1").(GunProperty)
fmt.Println(p2.Shoot())
}
// 设计枪属性 具体享元角色
type GunProperty interface {
// 射击属性
Shoot() string
}
type GunBase struct {
ShootType string
}
func NewGunBase() *GunBase {
return &GunBase{"manual"}
}
func (g *GunBase) Shoot() string {
return g.ShootType
}
// 冲锋枪
type SubMachineGun struct {
base GunProperty
AutoShoot string
}
func NewSubMachineGun(base GunProperty, shootType string) *SubMachineGun {
return &SubMachineGun{base, shootType}
}
func (s *SubMachineGun) Shoot() string {
return s.base.Shoot() + s.AutoShoot
}
// 抽象享元角色
type Element struct {
value interface{}
}
func NewElement(value interface{}) *Element {
return &Element{value}
}
// 享元工厂角色
type FlyWeightPattern struct {
pool map[string]*Element
m *sync.RWMutex
}
func (f *FlyWeightPattern) GetElement(key string) interface{} {
f.m.RLock()
defer f.m.RUnlock()
return f.pool[key].value
}
func (f *FlyWeightPattern) SetElement(key string, value interface{}) {
n := NewElement(value)
f.m.Lock()
defer f.m.Unlock()
f.pool[key] = n
}
func NewFlyWeightPattern() *FlyWeightPattern {
f := FlyWeightPattern{}
f.pool = map[string]*Element{}
f.m = &sync.RWMutex{}
return &f
}
执行结果如下:
manual
manualauto