【结构型模式】代理模式

文章目录

代理模式

什么是代理模式?

代理模式是结构型模式的基础,结构型模式通常用于类与类之间的组合场景当中。

代理模式可以为其他对象提供一种代理,以控制这个对象对其他类对象的访问。

一个典型的例子是,在「网络游戏」场景当中,我们作为玩家直接参与游戏进行升级可能较慢,这个时候可以通过代理(游戏代练)帮助我们升级,代理在帮助我们升级(完成我们本来要做的工作)的同时,还能够帮我们提升装备的质量(完成了额外的工作)。

代理模式中的角色和职责

代理模式的标准类图如下:

  • Subject(抽象主题):真实主题与代理主题的共同接口,比如"购物"。
  • RealSubject(具体主题):定义了代理劫色所代表的真实对象,比如"去海南购物"、"去韩国购物"、"去马来西亚购物"。
  • Proxy(代理主题角色):含有对真实主题角色的引用,当通过代理来完成 Request 时,完成前与完成后可以进行自定义的操作,实现 PreRequest 和 PostRequest 即可。

代理模式的案例实现

参考《Easy 搞定 Golang 设计模式》,此处引入一个"海外购物"的例子来实现代理模式。

go 复制代码
package main

import "fmt"

/* 以海外购物为主题, 实现代理模式 */
type Goods struct {
	Kind string // 商品种类
	Fact bool   // 商品真伪
}

// ---------- 抽象层 ----------
// 定义一个抽象的购物主题
type Shopping interface {
	Buy(goods *Goods)
}

// ---------- 实现层 ----------
// 实现具体的购物主题
type HainanShopping struct{}

func (hs *HainanShopping) Buy(goods *Goods) {
	fmt.Printf("去海南购物, 买了: %s\n", goods.Kind)
}

type ShouerShopping struct{}

func (ss *ShouerShopping) Buy(goods *Goods) {
	fmt.Printf("去首尔购物, 买了: %s\n", goods.Kind)
}

type JilongpoShopping struct{}

func (js *JilongpoShopping) Buy(goods *Goods) {
	fmt.Printf("去吉隆坡购物, 买了: %s\n", goods.Kind)
}

// 接下来实现一个"海外购物"的代理
type OverseaProxy struct {
	shopping Shopping // 成员是抽象的接口类型, 这样就可以适配不同的具体主题
}

func (op *OverseaProxy) distinguish(goods *Goods) bool {
	fmt.Printf("对[%s]进行了验货.\n", goods.Kind)
	if !goods.Fact {
		fmt.Printf("发现假货, 交易终止.\n")
	}
	return goods.Fact
}

func (op *OverseaProxy) check(goods *Goods) {
	fmt.Printf("对[%s]进行了海关安检\n", goods.Kind)
}

func (op *OverseaProxy) Buy(goods *Goods) {
	// 1. 先验货: PreRequest
	if op.distinguish(goods) {
		// 2. 验货成功, 购买: Request
		op.shopping.Buy(goods)
		// 3. 海关安检: PostRequest
		op.check(goods)
	}
}

// 创建一个代理, 并配置关联被代理的主题
func NewProxy(shopping Shopping) Shopping {
	return &OverseaProxy{shopping}
}

func main() {
	g1 := Goods{
		Kind: "椰树牌椰汁",
		Fact: true,
	}

	g2 := Goods{
		Kind: "猫山王榴莲",
		Fact: true,
	}

	// 不使用代理从海外购物
	var shopping Shopping
	shopping = &HainanShopping{}

	// 1. 先验货
	if g1.Fact {
		fmt.Printf("对[%s]进行了验货.\n", g1.Kind)
		shopping.Buy(&g1)
		fmt.Printf("对[%s]进行了海关安检.\n", g1.Kind)
	}

	// 使用代理模式购物
	fmt.Println("---------- 使用代理进行购物 ----------")
	var overseaProxy Shopping
	overseaProxy = &OverseaProxy{shopping}
	overseaProxy.Buy(&g1)
	overseaProxy.Buy(&g2)
}

代理模式的优缺点

优点

  1. 能够协调调用者与被调用者,一定程度上降低了系统的耦合度。
  2. 客户端可以针对抽象主题角色进行编程,增加和更换代理无需修改源码,符合开闭原则,使系统具有较好的灵活性和可拓展性。

缺点

  1. 代理实现较为复杂。
相关推荐
奈斯。zs6 小时前
java面向对象高级02——单例类(设计模式)
java·开发语言·设计模式
困鲲鲲6 小时前
设计模式:命令模式 Command
设计模式·命令模式
找不到、了9 小时前
Java设计模式之《备忘录模式》
设计模式·备忘录模式
困鲲鲲11 小时前
设计模式:责任链模式 Chain of Responsibility
设计模式·责任链模式
LoveC52111 小时前
设计模式之外观模式
设计模式·外观模式
星眠12 小时前
手写发布订阅设计模式
javascript·设计模式·面试
源代码•宸12 小时前
深入浅出设计模式——创建型模式之单例模式 Singleton
开发语言·c++·经验分享·单例模式·设计模式
未既13 小时前
java设计模式 -【责任链模式】
java·设计模式·责任链模式
IT小白架构师之路18 小时前
常用设计模式系列(十六)—策略模式
设计模式·bash·策略模式
二闹19 小时前
告别面条儿代码!这个设计模式让逻辑清晰10倍!
后端·设计模式