Design Patterns Handbook
  • Introduction
  • Creational Patterns
    • Builder
    • Factory
    • Abstract Factory
    • Factory Method
    • Prototype
    • Singleton
    • Object Pool
    • Revealing Constructor
  • Structural Patterns
    • Adapter
    • Composite
    • Proxy
    • Flyweight
    • Facade
    • Bridge
    • Decorator
    • Private Class Data
  • Behavioral Patterns
    • Template Method
    • Mediator
    • Chain Of Responsibility
    • Observer
    • Strategy
    • Command
    • State
    • Visitor
    • Memento
    • Interpreter
    • Null Object
    • Iterator
    • Middleware
  • Clean Code Patterns
    • Extract Method
    • Clarify Responsibility
    • Remove Duplications
    • Keep Refactoring
    • Always Unit Test
    • Create Data Type
    • Comment to Better Name
    • Consistent Naming
    • If-else over ternary operator
    • Composition over Inheritance
    • Too Many Returns
    • Private to Interface
  • Anti Patterns
    • Big Ball of Mud
    • Singleton
    • Mad Scientist
    • Spaghetti Code
    • It Will Never Happen
    • Error Codes
    • Commented Code
    • Abbreviations
    • Prefixes
    • Over Patternized
    • Generic Interface over Function
Powered by GitBook
On this page
  • Example - Secured commands
  • Example - Proxy in JavaScript

Was this helpful?

  1. Structural Patterns

Proxy

A proxy is an object that controls access to another object. They both must have the same interface (methods and methods signatures).

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

  • Use an extra level of indirection to support distributed, controlled, or intelligent access.

  • Add a wrapper and delegation to protect the real component from undue complexity.

A proxy is useful to do data validation, security, caching, logging, lazy initialization or implement a remote object logic.

Example - Secured commands

We are going to use Proxy pattern to secure some commands that should be accessible only for administrators. CommandExecutorProxy class makes sure the user who is trying to execute a command is the administrator.

interface CommandExecutor {
    void execute(String s);
}

class CommandExecutorImpl implements CommandExecutor {

    @Override
    public void execute(String s) {
        System.out.println("> " + s);
    }
}

class CommandExecutorProxy implements CommandExecutor {

    private CommandExecutor executor = new CommandExecutorImpl();

    private boolean isAdmin;

    public CommandExecutorProxy(String username, String password) {
        // TODO: find out if user is admin
        isAdmin = true;
    }

    @Override
    public void execute(String command) {
        if (isAdmin) {
            executor.execute(command);
        } else {
            throw new RuntimeException("Not authorized!");
        }
    }
}

Here is how we could use the code created above. If john is not an admin, the application should throw exception.

CommandExecutor executorProxy = new CommandExecutorProxy("john", "my-secret");
executorProxy.execute("ls -l");

Example - Proxy in JavaScript

Here is an example how to implement Proxy in JavaScript.

function createProxy(subject) {
  const proto = Object.getPrototypeOf(subject)
  function Proxy(subject) {
    this.subject = subject;
  }
  Proxy.prototype = Object.create(proto);
  // proxies function
  Proxy.prototype.hello = function() {
    return this.subject.hello() + ' there!';
  }
  // delegate function
  Proxy.prototype.goodbye = function() {
    return this.subject.goodbye.apply(this.subject, arguments)
  }
  return new Proxy(subject);
}

class MyObject {
  hello() {
    return "Hello";
  }
  goodbye() {
    return "Goodbye";
  }
}

const myObject = new MyObject();
const myProxiedObject = createProxy(myObject);
console.log(myProxiedObject instanceof MyObject); // return true
console.log(myProxiedObject.hello());
console.log(myProxiedObject.goodbye());

Or there is easier way to create proxy, taking advantage of dynamic typing in JavaScript.

function createProxy(subject) {
  return {
    hello: () => subject.hello() + ' there!',
    goodbye: () => subject.goodbye(),
  };
}

const myObject = new MyObject();
const myProxiedObject = createProxy(myObject);
console.log(myProxiedObject instanceof MyObject); // return false
console.log(myProxiedObject.hello());
console.log(myProxiedObject.goodbye());

ES2015 contains Proxy implementation.

class MyObject {
  constructor(name) {
    this.name = name;
  }
}
const myObj = new MyObject("Celeste");
const myProxied = new Proxy(myObj, {
  get: (target, property) => target[property].toUpperCase()
});
console.log(myProxied.name); // prints "CELESTE"
PreviousCompositeNextFlyweight

Last updated 5 years ago

Was this helpful?