代理模式
我们在Decorator设计模式的时候看到可以使用不同的方法来增强一个对象的功能. Proxy模式也一样, 但是它的目的通常是在尽可能地保留原有API的功能的基础上提供内部的功能增强.
Proxy并不是一种同质(homogeneous)API. 因为人们建立了各种不同的proxy来实现不同的目的. 在本章中我们会选择性地介绍一些, 你可以在网络上看到更多的proxy.
12.1 Smart Pointers
最简单直观的Proxy模式的使用是智能指针. 智能指针是对指针的封装, 它会持有引用计数, 重载某些操作, 但是, 总体来说, 会提供和普通指针一样的操作接口.
1 | struct BandAccount |
12.1 Property Proxy
在其他的一些语言中, 名词property指代一个字段(field)和对字段的getter/setter
方法. 在C++中没有属性, 但是我们可以建立一个property proxy来实现这个功能.
本质上说, property proxy是一个伪装成属性的类.
1 | template <typename T> |
这样, Property<T>
是T的一个替代品. 比如, 我们这样使用它:
1 | struct Creature |
属性的使用:
1 | Creature creature; |
12.2 Virtual Proxy
如果你试图解引用(dereference)一个nullptr
或一个未初始化的指针, 就会出问题. 但是很多时候, 我们并不希望对象被过早的创建, 而只是在被访问时才创建.
这种做法被称为lazy instantiation. 接下来我们会创建一个proxy.
考虑一个典型的Image
接口
1 | struct Image |
一个Bitmap的eager 实现会在它创建时立即加载数据, 即使它并不需要. 比如下面的代码:
1 | struct Bitmap : Image |
只要对象被创建, 就会加载图像:
1 | Bitmap img{"pokemon.jpg"}; // 从pokemon.jpg中加载图像 |
而这并不是我们想要的. 我们想要的是只有在draw()
方法被调用时才加载的类. 当然我们可以回头重新修改Bitmap
的代码. 但是假如我们不能修改代码该怎么办?
我们要做的就是创建一个virtual proxy, 它包含了原先的Bitmap
, 提供了相同的接口, 仍然能够被原先使用Bitmap
的程序使用.
1 | struct LazyBitmap : Image |