【结构型模式】代理模式

文章目录

代理模式

什么是代理模式?

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

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

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

代理模式中的角色和职责

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

  • 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. 代理实现较为复杂。
相关推荐
何中应2 小时前
【设计模式-4.11】行为型——解释器模式
java·设计模式·解释器模式
WispX8883 小时前
【设计模式】门面/外观模式
java·开发语言·设计模式·系统架构·外观模式·插件·架构设计
蔡蓝3 小时前
设计模式-外观模式
microsoft·设计模式·外观模式
琢磨先生David3 小时前
简化复杂系统的优雅之道:深入解析 Java 外观模式
java·设计模式·外观模式
on the way 12315 小时前
结构性设计模式之Flyweight(享元)
java·设计模式·享元模式
暴躁哥20 小时前
深入理解设计模式之访问者模式
设计模式·访问者模式
佩奇的技术笔记20 小时前
从Java的JDK源码中学设计模式之装饰器模式
java·设计模式·装饰器模式
on the way 12320 小时前
结构型设计模式之Proxy(代理)
设计模式·代理模式
YGGP1 天前
【结构型模式】装饰器模式
设计模式
将编程培养成爱好1 天前
《复制粘贴的奇迹:小明的原型工厂》
c++·设计模式·原型模式