设计模式 结构型模式

131 阅读3分钟

结构型模式

适配器模式

将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者,而无需修改原有代码

场景:系统需要使用现有的类,而这些类的接口不符合系统的需要

//适的目标接口
type Target interface {
	Request()
}

//被适配的目标接口
type Adaptee interface {
	SpecificRequest() string
}
//被适配接口的工厂函数
func NewAdapteeFactory() Adaptee{
	return &AdapteeImpl{}
}
//被适配的目标类
type AdapteeImpl struct {}
func (*AdapteeImpl)SpecificRequest() string {
	fmt.Println("AdapteeImpl.SpecificRequest...")
	return ""
}

//转换Adaptee为Target的适配器
type Apater struct {
	Adaptee
}
func (apater *Apater)Request() {
	apater.SpecificRequest()
}
//适配器的工厂方法
func NewApater(adaptee Adaptee) Target {
	return &Apater{
		Adaptee: adaptee,
	}
}

func main() {
	adaptee := NewAdapteeFactory()
	target := NewApater(adaptee)
	target.Request()
}

桥接模式

一个作为桥的接口,使得实体类的功能独立于接口实现类

//DrawAPI 画图抽象接口,桥接模式的抽象接口
type DrawApi interface {
	DrawCircle(radius int, x int, y int)
}

//RedCircle 红色圆的类,桥接模式接口
type RedCircle struct {}
//实例化红色圆
func NewRedCircle() *RedCircle{
	return &RedCircle{}
}
//NewRedCircle 实例化红色圆
func (s *RedCircle) DrawCircle(radius int, x int, y int) {
	fmt.Println("red, radius、x、y:", radius, x, y)
}
//RedCircle 绿色圆的类,桥接模式接口
type GreenCircle struct {}
//NewRedCircle 实例化绿色圆
func (s *GreenCircle) DrawCircle(radius int, x int, y int) {
	fmt.Println("green, radius、x、y:", radius, x, y)
}

//ShapeCircle 桥接模式的实体类
type ShapeCircle struct {
	Radius  int
	X       int
	Y       int
	drawAPI DrawApi
}

//NewShapeCircle 实例化桥接模式实体类
func NewShapeCircle(radius, x, y int, drawAPI DrawApi) *ShapeCircle {
	return &ShapeCircle{
		Radius:  radius,
		X:       x,
		Y:       y,
		drawAPI: drawAPI,
	}
}

//Draw 实体类的Draw方法
func (sc *ShapeCircle) Draw() {
	sc.drawAPI.DrawCircle(sc.Radius, sc.X, sc.Y)
}

func main() {
	shapeCircle := NewShapeCircle(10,100, 100, &RedCircle{})
	shapeCircle.Draw()

	shapeCircle = NewShapeCircle(10,100, 100, &GreenCircle{})
	shapeCircle.Draw()
}

组合模式

用于把一组相似的对象当作一个单一的对象

将对象组合成树形结构,以表示“部分-整体”的层次结构。使得用户对单个对象的使用具有一致性

在树形结构的问题中,模糊了简单元素和复杂元素的概念

//Employee 职员类
type Employee struct {
	Name         string
	Dept         string
	Salary       int
	Subordinates *list.List
}

//NewEmployee 实例化职员类
func NewEmployee(name, dept string, salary int) *Employee {
	sub := list.New()
	return &Employee{
		Name:         name,
		Dept:         dept,
		Salary:       salary,
		Subordinates: sub,
	}
}

//Add 添加职员的下属
func (e *Employee) Add(emp Employee) {
	e.Subordinates.PushBack(emp)
}

//Remove 删除职员的下属
func (e *Employee) Remove(emp Employee) {
	for i := e.Subordinates.Front(); i != nil; i = i.Next() {
		if reflect.DeepEqual(i.Value, emp) {
			e.Subordinates.Remove(i)
		}
	}
}

//GetSubordinates 获取职员下属列表
func (e *Employee) GetSubordinates() *list.List {
	return e.Subordinates
}

//ToString 获取职员的string信息
func (e *Employee) ToString() string {
	return "[ Name: " + e.Name + ", dept: " + e.Dept + ", Salary: " + strconv.Itoa(e.Salary) + " ]"
}


func main() {
	ceo := NewEmployee("lee", "ceo", 9999)

	pm := NewEmployee("wang", "technology", 1000)
	programmer1 := NewEmployee("jolin", "technology", 8000)
	programmer2 := NewEmployee("jay", "technology", 8000)

	minister := NewEmployee("zhou", "accounting", 5000)
	finance1 := NewEmployee("zzz", "accounting", 3000)
	finance2 := NewEmployee("Mary", "accounting", 2900)

	ceo.Add(*pm)
	ceo.Add(*minister)

	pm.Add(*programmer1)
	pm.Add(*programmer2)

	minister.Add(*finance1)
	minister.Add(*finance2)

	//打印所有职员
	fmt.Println(ceo.ToString())
	for i := ceo.Subordinates.Front(); i != nil; i = i.Next() {
		em := i.Value.(Employee)
		fmt.Println(em.ToString())
		for j := i.Value.(Employee).Subordinates.Front(); j != nil; j = j.Next() {
			em := j.Value.(Employee)
			fmt.Println(em.ToString())
		}
	}
}

装饰模式

动态的给一个对象增加一些额外的职责

studygolang.com/articles/18…

外观模式

为复杂的子系统中提供一个统一的接入接口,外部所有对子系统的调用都通过这个外观接口进行统一访问,降低客户端与子系统的耦合度

type Shape interface {
	Draw()
}
type Circle struct {}
func (*Circle)Draw() {
	fmt.Println("draw circle...")
}
type Rectangle struct {}
func (*Rectangle)Draw() {
	fmt.Println("draw rectangle...")
}

//外观类
type ShapeMaker struct {
	circle Circle
	rectangle Rectangle
}
func NewShapeMaker() *ShapeMaker {
	return &ShapeMaker{
		circle:    Circle{},
		rectangle: Rectangle{},
	}
}
func (shapeMk *ShapeMaker)DrawCircle() {
	shapeMk.circle.Draw()
}
func (shapeMk *ShapeMaker)DrawRectangle() {
	shapeMk.rectangle.Draw()
}

func main() {
	shapeMaker := NewShapeMaker()
	shapeMaker.DrawCircle()
	shapeMaker.DrawRectangle()
}

享元模式

尝试重用现有的同类对象,如果未找到匹配的对象,则创建新的对象

用于减少创建对象的数量,以减少内存占用和提高性能

studygolang.com/articles/30…

代理模式

未其他对象提供一种代理以控制对这个对象的访问

blog.csdn.net/qq_35703848…