Skip to content

Instantly share code, notes, and snippets.

@OriginUnknown
Created June 23, 2015 11:40
Show Gist options
  • Save OriginUnknown/3559ee4e4cd7e747fcfc to your computer and use it in GitHub Desktop.
Save OriginUnknown/3559ee4e4cd7e747fcfc to your computer and use it in GitHub Desktop.
JavaScript OOP Design Patterns - Bridge Pattern
<!doctype html>
<html lang="en">
<head>
<title>Bridge pattern</title>
</head>
<body>
<script type="text/javascript">
/*
* REMOTE CONTROL BUTTONS
* Concrete R/C Buttons
* ON
* OFF
* VOLUME UP
* VOLUME DOWN
*
* Dynamic R/C Buttons
* UP Button
* DOWN Button
* LEFT Button
* RIGHT Button
* MIDDLE Button
*/
var EntertainmentSystem = (function () {
var self = {};
//Shared private methods
function previousItemIsCurrent ( index ) {
return index === 0;
}
function endOfListItem ( index, listings ) {
return index + 1 === listings.length;
}
//Abstract classes
function AbstractRemoteControl ( ed ) {
var _device = ed;
var turnDeviceOn = _device.on.bind( _device ),
turnDeviceOff = _device.off.bind( _device ),
incrementVolume = _device.volumeUpButton.bind( _device ),
decrementVolume = _device.volumeDownButton.bind( _device );
return {
"on" : turnDeviceOn,
"off" : turnDeviceOff,
"volumeUpButton" : incrementVolume,
"volumeDownButton" : decrementVolume
}
}
//Abstract class for all derived entertainment devices.
function AbstractEntertainmentDevice () {
//private properties and methods
var _msg = "", _maxVolumeLevel = null, _volumeLevel = 0,
validMaxVolumeSettings = function ( v ) {
return v !== null && v !== undefined && v !== 0 && typeof(v) === 'number'; //returns boolean
};
//public methods to be returned
var abOn = function () {
_msg = this.getDeviceName.call( this ) + " is on";
return _msg;
};
var abOff = function () {
_msg = this.getDeviceName.call( this ) + " is turned off";
return _msg;
};
var abGetMaxVolumeLevel = function () {
if ( _maxVolumeLevel !== null ) {
return _maxVolumeLevel;
} else {
throw new Error( "Maximum volume level has not been set. Please set the maximum volume level." );
}
};
var abSetMaxVolumeLevel = function ( newMaxVolumeLevel ) {
if ( validMaxVolumeSettings( newMaxVolumeLevel ) ) {
_maxVolumeLevel = newMaxVolumeLevel;
return _maxVolumeLevel;
} else {
throw new Error( "Invalid maximum volume level. Value must be a number greater than 0 and is not null or undefined." );
}
};
var abVolumeUpButton = function () {
if ( _volumeLevel > - 1 && _volumeLevel < _maxVolumeLevel ) {
_volumeLevel ++;
_msg = "Volume Level for " + this.getDeviceName.call( this ) + " has been increased to " + _volumeLevel;
return _msg;
} else {
_msg = "Unable to increase volume level for " + this.getDeviceName.call( this ) + ". Current volume level is " + _volumeLevel;
return _msg;
}
};
var abVolumeDownButton = function () {
if ( _volumeLevel > 0 && _volumeLevel <= _maxVolumeLevel ) {
_volumeLevel --;
_msg = "Volume Level for " + this.getDeviceName.call( this ) + " has been decreased to " + _volumeLevel;
return _msg;
} else {
_msg = "Unable to decrease volume level for " + this.getDeviceName.call( this ) + ". Current volume level is " + _volumeLevel;
return _msg;
}
};
return {//All derived entertainment devices will have the following methods below by default
"on" : abOn,
"off" : abOff,
"setMaxVolumeLevel" : abSetMaxVolumeLevel,
"getMaxVolumeLevel" : abGetMaxVolumeLevel,
"volumeUpButton" : abVolumeUpButton,
"volumeDownButton" : abVolumeDownButton
}
}
//Concrete implementation for one type of entertainment device : Television
self.AddNewTelevision = function ( tvName, maxChannelNum ) {
var newTelly = AbstractEntertainmentDevice(),//EXTENDS the AbstractEntertainmentDevice class
//private variables and methods below
deviceType = "Television",
deviceName = tvName || deviceType, currentChannel = 1,
tvListings = [ "The Simpsons", "Hollyoaks", "Channel 4 News" ],
tvListingIndex = 0, msg = "", maxChannelNumber = parseInt( maxChannelNum ) || null,
validMaxChannelNumber = function ( v ) {
return v !== null && v !== undefined && v > 0 && typeof(v) === "number";
},
nextChannelIsZero = function () {
return currentChannel - 1 === 0;
},
okToIncreaseChannel = function () {
return maxChannelNumber !== null && currentChannel > 0 && currentChannel < maxChannelNumber;
};
//public methods for consumption
//Exclusive methods for the Television sub class
newTelly.setDeviceName = function ( newName ) {
if ( typeof(newName) === 'string' ) {
deviceName = newName;
return deviceName;
} else {
throw new Error( "Invalid name for Television device. Name should be a string" );
}
};
newTelly.getDeviceName = function () {
return deviceName;
};
newTelly.getMaxChannels = function () {
if ( validMaxChannelNumber( maxChannelNumber ) ) {
return maxChannelNumber;
} else {
throw new Error( "Maximum channel number has not been set. Please set the maximum channel number." );
}
};
newTelly.setMaxChannels = function ( newMaxChannelNumber ) {
if ( validMaxChannelNumber( newMaxChannelNumber ) ) {
maxChannelNumber = newMaxChannelNumber;
return this; //this is returned for optional "chaining" purposes
} else {
throw new Error( "Invalid value. Max channel value should be a number greater than 0." );
}
};
//Specific implementations of the signature methods for the Television sub class
newTelly.upButton = function () {
if ( okToIncreaseChannel() ) {
currentChannel ++;
msg = "Current channel is " + currentChannel;
return msg;
} else {
throw new Error( "Unable to increase the channel" );
}
};
newTelly.downButton = function () {
if ( ! nextChannelIsZero() ) {
currentChannel --;
msg = "Current Channel is " + currentChannel;
return msg;
} else {
throw new Error( "Unable to decrease the channel" );
}
};
newTelly.leftButton = function () {
if ( previousItemIsCurrent( tvListingIndex ) ) {
tvListingIndex = 0;
return tvListings[ tvListingIndex ];//return current listing (first item in the array)
} else {
msg = tvListings[ tvListingIndex ];
tvListingIndex --;
return msg;
}
};
newTelly.rightButton = function () {
if ( endOfListItem( tvListingIndex, tvListings ) ) {
msg = "Unable to get further listings at this time";
return msg;
} else {
tvListingIndex ++;
return tvListings[ tvListingIndex ];
}
};
return newTelly;
};
//Concrete implementation of the AbstractRemoteControl class for the Television remote control
self.CreateTelevisionRemoteControl = function ( tv ) {
var telly = tv, tvRemoteControl = AbstractRemoteControl( tv );//EXTENDS the AbstractRemoteControl class
//Add the Television specific methods onto the television remote control object
tvRemoteControl.upButton = telly.upButton;
tvRemoteControl.downButton = telly.downButton;
tvRemoteControl.leftButton = telly.leftButton;
tvRemoteControl.rightButton = telly.rightButton;
return tvRemoteControl;
};
self.AddNewDVDPlayer = function ( dvdPlayerName ) {
var newDVDPlayer = AbstractEntertainmentDevice(),
deviceType = "DVD Player",
deviceName = dvdPlayerName || deviceType,
volumeLevel = 0, maxVolumeLevel = null, msg = "",
chapterIndex = 0, enableSubtitles = false,
chapters = [ "Bart the Fink", "Krusty gets Kancelled", "Lisa Vs the Monorail" ];//DVD chapters
newDVDPlayer.setDeviceName = function ( newName ) {
if ( typeof(newName) === 'string' ) {
deviceName = newName;
return deviceName;
} else {
throw new Error( "Invalid name for DVD Player device. Name should be a string" );
}
};
newDVDPlayer.getDeviceName = function () {
return deviceName;
};
//DVD Class extends the AbstractEntertainmentDevice class by adding DVD specific methods to this function
newDVDPlayer.upButton = function () {
if ( ! enableSubtitles ) {
enableSubtitles = true;
msg = "Subtitles are enabled";
return msg;
} else {
msg = "Subtitles have already been enabled";
return msg;
}
};
newDVDPlayer.downButton = function () {
if ( enableSubtitles ) {
enableSubtitles = false;
msg = "Subtitles have been disabled";
return msg;
} else {
msg = "Subtitles have already been disabled";
return msg;
}
};
newDVDPlayer.leftButton = function () {
if ( previousItemIsCurrent( chapterIndex ) ) {
chapterIndex = 0;
return chapters[ chapterIndex ];
} else {
msg = chapters[ chapterIndex ];
chapterIndex --;
return msg;
}
};
newDVDPlayer.rightButton = function () {
if ( endOfListItem( chapterIndex, chapters ) ) {
msg = "End of chapter listings";
return msg;
} else {
chapterIndex ++;
return chapters[ chapterIndex ];
}
};
return newDVDPlayer;
};
self.CreateDVDPlayerRemoteControl = function ( dvdPlayer ) {
var dvdDevice = dvdPlayer, dvdRemoteControl = AbstractRemoteControl( dvdPlayer );//EXTENDS the AbstractRemoteControl class
//Add the DVD player specific methods onto the DVD Player remote control object
dvdRemoteControl.upButton = dvdDevice.upButton;
dvdRemoteControl.downButton = dvdDevice.downButton;
dvdRemoteControl.leftButton = dvdDevice.leftButton;
dvdRemoteControl.rightButton = dvdDevice.rightButton;
return dvdRemoteControl;
};
return self;
})();
//Set up your telly - add it to your entertainment system
var Samsung = EntertainmentSystem.AddNewTelevision( "Chump" ).setMaxChannels( 3 );
Samsung.setMaxVolumeLevel( 3 );
//Use your remote control to control your telly by passing in your tv as an argument
//for the remote control to use
var SamsungRemoteControl = EntertainmentSystem.CreateTelevisionRemoteControl( Samsung );
console.log( SamsungRemoteControl.on() );
console.log( SamsungRemoteControl.off() );
console.log( SamsungRemoteControl.volumeUpButton() );//volume 1
console.log( SamsungRemoteControl.volumeUpButton() );//volume 2
console.log( SamsungRemoteControl.volumeUpButton() );//volume 3
console.log( SamsungRemoteControl.volumeUpButton() );// returns "Unable to increase volume level for Chump. Current volume level is 3"
console.log( SamsungRemoteControl.volumeDownButton() );//volume 3
console.log( SamsungRemoteControl.volumeDownButton() );//volume 2
console.log( SamsungRemoteControl.volumeDownButton() );//volume 1
console.log( SamsungRemoteControl.volumeDownButton() );// returns "Unable to decrease volume level for Chump. Current volume level is 0"
//Television specific remote controls - idea for controls was based on Sky Digital's box
console.log( SamsungRemoteControl.upButton() );//channel 2
console.log( SamsungRemoteControl.upButton() );//channel 3
//console.log(SamsungRemoteControl.upButton());//returns an Exception
console.log( SamsungRemoteControl.downButton() );//channel 2
console.log( SamsungRemoteControl.downButton() );//channel 1
//console.log(SamsungRemoteControl.downButton());//returns Exception
console.log( SamsungRemoteControl.leftButton() );//returns scheduled tv show for current time -> "The Simpsons"
console.log( SamsungRemoteControl.rightButton() );//returns "Hollyoaks"
console.log( SamsungRemoteControl.rightButton() );//returns "Channel 4 News"
console.log( SamsungRemoteControl.rightButton() );//return "Unable to get further listings at this time"
//Add your brand spanking new DVD player to your entertainment system
var SonyDVDPlayer = EntertainmentSystem.AddNewDVDPlayer( "Sony Universal" );
SonyDVDPlayer.setMaxVolumeLevel( 4 );
//Tell your DVD remote control to control the DVD player
var DVDPlayerRemoteControl = EntertainmentSystem.CreateDVDPlayerRemoteControl( SonyDVDPlayer );
//Play around with your DVD remote control device
console.log( DVDPlayerRemoteControl.on() );//Sony Universal is on
console.log( DVDPlayerRemoteControl.off() );//Sony Universal is turned off
console.log( DVDPlayerRemoteControl.volumeUpButton() );//DVD volume increased to 1
console.log( DVDPlayerRemoteControl.volumeUpButton() );//DVD volume increased to 2
console.log( DVDPlayerRemoteControl.volumeDownButton() );//DVD volume decreased to 1
//DVD player remote control specific commands
console.log( DVDPlayerRemoteControl.upButton() );//returns "Subtitles are enabled"
console.log( DVDPlayerRemoteControl.upButton() );//returns "Subtitles have already been enabled"
console.log( DVDPlayerRemoteControl.downButton() );//returns "Subtitles have been disabled"
console.log( DVDPlayerRemoteControl.downButton() );//return "Subtitles have already been disabled"
console.log( DVDPlayerRemoteControl.leftButton() );//returns "Bart the Fink"
console.log( DVDPlayerRemoteControl.rightButton() );//returns "Krusty gets Kancelled"
console.log( DVDPlayerRemoteControl.rightButton() );//returns "Lisa Vs the Monorail"
console.log( DVDPlayerRemoteControl.rightButton() );//returns "End of chapter listings"
console.log( DVDPlayerRemoteControl.leftButton() );//returns "Lisa Vs the Monorail"
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment