+TypeScript example
Callers draw through IImage, while the proxy decides when to create the real object. Keeping creation control separate prevents every screen from repeating the lazy-loading check.
// Let callers use the real subject and its proxy through the same contract.
interface IImage { draw(): string; }
class RealImage implements IImage {
static created = 0;
constructor() { RealImage.created++; }
draw(): string { return "draw image"; }
}
// Control construction time and delegate the actual work to the created object.
class ImageProxy implements IImage {
#image: RealImage | undefined;
draw(): string {
this.#image ??= new RealImage();
return this.#image.draw();
}
}
const image: IImage = new ImageProxy();
console.log(RealImage.created);
console.log(image.draw());
console.log(image.draw());
console.log("created: " + RealImage.created);
0
draw image
draw image
created: 1
The #image field expresses the deferred creation performed by C# Lazy<RealImage>. It reuses the object rather than caching draw() results, and reads no image files.