学习笔记:代理、装饰器、适配器模式
本文最后更新于248 天前,其中的信息可能已经过时,如有错误请发送邮件到lvlvko233@qq.com

代理模式

代理模式是一种结构型设计模式,允许我们控制对其他对象的访问。它通过创建一个代理对象来代表另一个对象,从而在访问原对象时提供额外的功能。

场景示例:网络请求处理

假设我们有一个处理网络请求的系统。我们将使用这个场景来展示三种设计模式的实现。

package main

import "fmt"

// HttpRequester 接口定义了发送 HTTP 请求的方法
type HttpRequester interface {
    SendRequest(url string) string
}

// RealHttpRequester 是实际发送 HTTP 请求的结构体
type RealHttpRequester struct{}

func (r *RealHttpRequester) SendRequest(url string) string {
    return fmt.Sprintf("Sending real HTTP request to %s", url)
}

// HttpProxy 是 HTTP 请求的代理
type HttpProxy struct {
    realRequester *RealHttpRequester
}

func (p *HttpProxy) SendRequest(url string) string {
    if p.realRequester == nil {
        p.realRequester = &RealHttpRequester{}
    }
    fmt.Println("Proxy: Logging request")
    result := p.realRequester.SendRequest(url)
    fmt.Println("Proxy: Logging response")
    return result
}

func main() {
    proxy := &HttpProxy{}
    result := proxy.SendRequest("<https://example.com>")
    fmt.Println(result)
}

这段代码展示了代理模式的实现:

  1. HttpRequester 接口定义了 SendRequest 方法。
  2. RealHttpRequester 实现了实际的 HTTP 请求发送。
  3. HttpProxy 作为代理,包装了 RealHttpRequester。它在发送请求前后添加了日志记录功能。
  4. main 函数中,我们使用 HttpProxy 来发送请求,而不直接使用 RealHttpRequester

装饰器模式

装饰器模式是一种结构型设计模式,它允许我们动态地给对象添加新的行为,而不改变其结构。

场景示例:增强的网络请求处理

我们将在前面的例子基础上,使用装饰器模式来添加额外的功能。

package main

import (
    "fmt"
    "strings"
)

// HttpRequester 接口保持不变
type HttpRequester interface {
    SendRequest(url string) string
}

// RealHttpRequester 保持不变
type RealHttpRequester struct{}

func (r *RealHttpRequester) SendRequest(url string) string {
    return fmt.Sprintf("Sending real HTTP request to %s", url)
}

// CacheDecorator 是缓存装饰器
type CacheDecorator struct {
    requester HttpRequester
    cache     map[string]string
}

func NewCacheDecorator(r HttpRequester) *CacheDecorator {
    return &CacheDecorator{
        requester: r,
        cache:     make(map[string]string),
    }
}

func (c *CacheDecorator) SendRequest(url string) string {
    if result, found := c.cache[url]; found {
        return "From cache: " + result
    }
    result := c.requester.SendRequest(url)
    c.cache[url] = result
    return result
}

// CompressionDecorator 是压缩装饰器
type CompressionDecorator struct {
    requester HttpRequester
}

func (c *CompressionDecorator) SendRequest(url string) string {
    result := c.requester.SendRequest(url)
    return "Compressed: " + strings.Replace(result, " ", "", -1)
}

func main() {
    realRequester := &RealHttpRequester{}
    cachedRequester := NewCacheDecorator(realRequester)
    compressedCachedRequester := &CompressionDecorator{requester: cachedRequester}

    fmt.Println(compressedCachedRequester.SendRequest("<https://example.com>"))
    fmt.Println(compressedCachedRequester.SendRequest("<https://example.com>")) // 这次会从缓存中获取
}

这段代码展示了装饰器模式的实现:

  1. CacheDecorator 添加了缓存功能。它存储请求结果,并在重复请求时返回缓存的结果。
  2. CompressionDecorator 添加了压缩功能(这里用简单的去空格来模拟)。
  3. main 函数中,我们将这些装饰器组合起来,创建了一个既有缓存又有压缩功能的 HTTP 请求器。

适配器模式

适配器模式是一种结构型设计模式,它允许不兼容的接口一起工作。

场景示例:适配第三方 HTTP 客户端

假设我们想使用一个第三方的 HTTP 客户端库,但它的接口与我们的 HttpRequester 不兼容。

package main

import "fmt"

// HttpRequester 接口保持不变
type HttpRequester interface {
    SendRequest(url string) string
}

// 假设这是第三方库的接口
type ThirdPartyHttpClient interface {
    Get(url string) (string, error)
}

// 第三方库的具体实现
type ConcreteThirdPartyClient struct{}

func (c *ConcreteThirdPartyClient) Get(url string) (string, error) {
    return fmt.Sprintf("Third party client requesting: %s", url), nil
}

// HttpClientAdapter 适配器
type HttpClientAdapter struct {
    thirdPartyClient ThirdPartyHttpClient
}

func (a *HttpClientAdapter) SendRequest(url string) string {
    result, err := a.thirdPartyClient.Get(url)
    if err != nil {
        return "Error: " + err.Error()
    }
    return "Adapted: " + result
}

func main() {
    thirdPartyClient := &ConcreteThirdPartyClient{}
    adapter := &HttpClientAdapter{thirdPartyClient: thirdPartyClient}

    result := adapter.SendRequest("<https://example.com>")
    fmt.Println(result)
}

这段代码展示了适配器模式的实现:

  1. ThirdPartyHttpClient 接口代表第三方库的接口,它与我们的 HttpRequester 接口不兼容。
  2. ConcreteThirdPartyClient 是第三方库的具体实现。
  3. HttpClientAdapter 是适配器,它实现了 HttpRequester 接口,但内部使用 ThirdPartyHttpClient 来执行实际的请求。
  4. main 函数中,我们创建了一个适配器,使得第三方客户端可以在我们的系统中使用。

三种模式的比较

  1. 目的:
    • 代理模式:控制对对象的访问
    • 装饰器模式:动态添加功能
    • 适配器模式:使不兼容的接口能够一起工作
  2. 结构:
    • 代理模式:代理和实际对象实现相同的接口
    • 装饰器模式:装饰器和被装饰对象实现相同的接口
    • 适配器模式:适配器实现目标接口,包含被适配对象
  3. 使用场景:
    • 代理模式:访问控制、延迟初始化、日志记录等
    • 装饰器模式:动态添加或移除对象功能
    • 适配器模式:集成新的库或API时
  4. 灵活性:
    • 代理模式:相对固定
    • 装饰器模式:非常灵活,可以动态组合
    • 适配器模式:主要用于接口转换
  5. 对原有代码的影响:
    • 代理模式:通常不改变原有代码
    • 装饰器模式:不改变原有代码
    • 适配器模式:不改变原有代码,但需要创建新的适配器类

三种模式的共同点和优劣

共同点:

  1. 都属于结构型设计模式
  2. 都包装原有对象
  3. 对客户端保持透明性
  4. 倾向于使用对象组合而不是继承
  5. 遵循开闭原则
  6. 符合单一职责原则
  7. 在原始对象和客户端之间创建中间层
  8. 允许在运行时动态改变对象的行为或结构

优劣比较:

  • 代理模式:
    • 优点:可以控制对对象的访问,增加安全性
    • 缺点:可能会增加系统的复杂度
  • 装饰器模式:
    • 优点:非常灵活,可以动态地添加功能
    • 缺点:可能会导致系统中小对象过多
  • 适配器模式:
    • 优点:可以让不兼容的接口一起工作
    • 缺点:有时候可能会增加代码的复杂度
感谢阅读~

评论

  1. 778
    Windows Edge
    已编辑
    8 月前
    2024-8-14 23:33:00

    ୧(๑•̀⌄•́๑)૭

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇