:::tips 本质上 代理模式是为了解决 在不破坏原始类的情况下 扩展类功能

:::

代理模式

:::tips 用处:

  • 通过引入代理来给原始类附加功能

好处:

  • 代码间解耦
  • 非侵入式

场景

  • 非功能性需求: 监控, 统计, 鉴权, 限流, 事务, 日志等

:::

golang

典型的代理模式

  1. package main
  2. import "fmt"
  3. // Userinfo 充值类
  4. type Userinfo struct {
  5. id string
  6. surplus int
  7. }
  8. func (u *Userinfo) Recharge(count int) {
  9. if count > 0 {
  10. u.surplus += count
  11. }
  12. }
  13. func (u *Userinfo) Payment(count int) {
  14. if count < 0 {
  15. u.surplus += count
  16. }
  17. }
  18. type UserInfoProxy struct {
  19. userinfo Userinfo
  20. }
  21. func (u *UserInfoProxy) Recharge(count int) {
  22. fmt.Println("Recharge before do something")
  23. u.userinfo.Recharge(count)
  24. fmt.Println("Recharge after do something")
  25. }
  26. func (u *UserInfoProxy) Payment(count int) {
  27. fmt.Println("Payment before do something")
  28. u.userinfo.Payment(count)
  29. fmt.Println("Payment after do something")
  30. }
  31. func main() {
  32. u := UserInfoProxy{Userinfo{"id", 100}}
  33. u.Recharge(50)
  34. u.Recharge(100)
  35. fmt.Println(u)
  36. }
  • 在外面包裹了一层, 的确没有侵入代码, 但是还是有个大麻烦, 那就是你需要实现父类的所有方法, 这会导致类的数量直接翻倍, 难以维护
  • 如果不是我们维护的代码, 比如 第三方类库, 也没办法直接定义一个接口, 这种代码可以通过继承来实现(golang不带, 所以在C#中再演示)

切片式

  1. package main
  2. import "fmt"
  3. // Userinfo 充值类
  4. type Userinfo struct {
  5. id string
  6. surplus int
  7. }
  8. func (u *Userinfo) Recharge(count int) {
  9. funcAop(func() {
  10. if count > 0 {
  11. u.surplus += count
  12. }
  13. })
  14. }
  15. func (u *Userinfo) Payment(count int) {
  16. funcAop(func() {
  17. if count < 0 {
  18. u.surplus += count
  19. }
  20. })
  21. }
  22. func funcAop(fn func()) {
  23. fmt.Println("before do something")
  24. fn()
  25. fmt.Println("after do something")
  26. }
  27. func main() {
  28. u := Userinfo{"id", 100}
  29. u.Recharge(50)
  30. u.Recharge(100)
  31. fmt.Println(u)
  32. }
  • golang参数可以是函数, 切片非常方便, 缺点是这样是侵入式的