design-patterns

Quick-reference guide to software design patterns with concise Dart examples.

View project on GitHub

Provides a surrogate or placeholder for another object to control access to it.

Common uses: lazy loading, access control, logging.

abstract class Image {
  void display();
}

class RealImage implements Image {
  final String _filename;

  RealImage(this._filename) {
    print('Loading $_filename from disk...');
  }

  @override
  void display() => print('Displaying $_filename');
}

class ProxyImage implements Image {
  final String _filename;
  RealImage? _realImage;

  ProxyImage(this._filename);

  @override
  void display() {
    _realImage ??= RealImage(_filename); // lazy load
    _realImage!.display();
  }
}

// Usage
final image = ProxyImage('photo.jpg'); // no loading yet
image.display(); // loads and displays
image.display(); // just displays (already loaded)