
//Subject: a pointer to a function plays the virtual draw()
typedef struct Graphic {
const char *fileName;
void (*draw)(struct Graphic *self);
} Graphic;
//RealSubject: it is costly to create
typedef struct {
Graphic base;
} Image;
//Request()
void imageDraw(Graphic *self) {
printf("draw %s\n", self->fileName);
}
Image *imageNew(const char *fileName) {
printf("load %s\n", fileName);
Image *image = malloc(sizeof *image);
*image = (Image){{fileName, imageDraw}};
return image;
}
//Proxy: the same Subject, the real image is made on the first draw()
typedef struct {
Graphic base;
Image *image;
} ImageProxy;
Image *getImage(ImageProxy *proxy) {
if (proxy->image == nullptr) {
proxy->image = imageNew(proxy->base.fileName);
}
return proxy->image;
}
void proxyDraw(Graphic *self) {
Graphic *image = &getImage((ImageProxy *)self)->base;
image->draw(image);
}
//Client
ImageProxy proxy = {{"1.png", proxyDraw}, nullptr};
Graphic *graphic = &proxy.base;
//operation without creating a RealSubject
const char *fileName = graphic->fileName;
//forwarded to the RealSubject
graphic->draw(graphic);
//printed: load 1.png
// draw 1.png
graphic->draw(graphic);
//printed: draw 1.png
printf("fileName: %s\n", fileName);
free(proxy.image);
Подменяет другой объект для контроля доступа к нему. Заместитель реализует интерфейс первоначального объекта.Read moreЗадача. В документе много больших картинок. Если программа загружает их все при открытии документа, открытие идёт медленно, хотя пользователь видит только первую страницу. Код, который показывает картинки, должен остаться прежним. Но загрузка должна ждать, пока картинка действительно понадобится. Идея. Заместитель встаёт на место другого объекта - реального субъекта. Интерфейс у них одинаковый, поэтому клиент не видит между ними разницы. Заместитель решает, когда и как пользоваться реальным субъектом. Этот вид, виртуальный заместитель, создаёт реальный субъект только при первом запросе, а потом передаёт ему каждый вызов. Другие виды заместителей проверяют права доступа, держат кэш или связываются с объектом на другом компьютере. Как читать пример. Реальный субъект - это изображение, которое дорого создавать. Заместитель хранит только имя файла и пустое место под изображение. В большинстве языков клиент сначала спрашивает имя файла, и заместитель отвечает сам. Когда клиент просит нарисовать изображение, заместитель создаёт настоящее изображение, запоминает его и передаёт вызов. Клиент работает только с заместителем. В некоторых языках вывод показывает ещё и момент, когда настоящее изображение загружается. Когда применять. Заместитель нужен, чтобы управлять доступом к объекту, не меняя ни сам объект, ни его клиентов. Типичные задачи - отложить дорогое создание, проверить права или посчитать вызовы. Если объект дёшев и нужен всегда, заместитель ни к чему: лишний уровень только замедляет код. Частая ошибка. Не сохранить созданный объект. Тогда заместитель создаёт новый реальный субъект при каждом вызове, и вся экономия пропадает. |