MENU
Object Relay
Sometimes, instead of extending and overriding a class entirely, we may wish to create an object out of another existing object instance instead. In such a design pattern, properties and methods may be changed or added. The practical uses include data validation, security, caching, lazy initialization, logging, remote objects, etc.
A surrogate / proxy(not the built-in class of 8.21) provides the same interface (ie. exposed APIs). In implementing this, the original functionalities may be reused and modified.
RESETRUNFULL
<!DOCTYPE html><html><body><script>
class C{
greet(){return 'Hello';}
hi(p){ return p+', hi.';}}function createProxyWithPrototype(subject){ // Composition
function MyProxy(subject){
this.subject = subject;
}
MyProxy.prototype = Object.create(Object.getPrototypeOf(subject));
MyProxy.prototype.greet = function(){
return this.subject.greet()+' world';
}
MyProxy.prototype.hi = function(){
return this.subject.hi.apply(this.subject,arguments);
}
return new MyProxy(subject);}var o = new C;var p = createProxyWithPrototype(o);console.log(p.greet()); // Hello worldconsole.log(p.hi('John')); // John, hi.console.log(p instanceof C); // true
</script></body><html>
<!DOCTYPE html><html><body><script>
class C{
greet(){return 'Hello';}
hi(p){ return p+', hi.';}}function createProxyWithoutPrototype(subject){//Composition
return {
greet:function(){
return subject.greet()+' world';
},
hi:function(){
return subject.hi.apply(subject,arguments);
}
}}var o = new C;var p = createProxyWithoutPrototype(o);console.log(p.greet()); // Hello worldconsole.log(p.hi('John')); // John, hi.console.log(p instanceof C); // false
</script></body><html>
<!DOCTYPE html><html><body><script>
class C{
greet(){return 'Hello';}
hi(p){ return p+', hi.';}}function createProxyByMonkeyPatching(subject){ // Object Augmentation
var greetOri = subject.greet;// prevents infinite recursion
var hiOri = subject.hi; // prevents infinite recursion
subject.greet = function(){
return greetOri.call(this)+' world';}
subject.hi = function(){
return hiOri.apply(subject,arguments);}
return subject;}var o = new C;var p = createProxyByMonkeyPatching(o);console.log(p.greet()); // Hello worldconsole.log(p.hi('John')); // John, hi.console.log(p instanceof C); // falseconsole.log(o.greet()); // Hello world
(original subject changed too)
</script></body><html>
A decorator augments/extends the original interface with new functionalities. The techniques of implementation are similar to those in 1) but involve defining new methods instead of merely overriding existing ones.
An adaptor provides a different interface. A function takes in a subject object, exposes a different set of methods, and returns an object.