- 浏览: 242690 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
saiyaren:
你对hiphop的深入程度到了什么程度了?想和你进行探讨一下
facebook hiphop php vm 实现概述 -
eric_weitm:
lj3362569 写道可以再讲具体点么?还有现有的hipho ...
facebook hiphop php vm 实现概述 -
lj3362569:
可以再讲具体点么?还有现有的hiphop不支持哪些功能?
facebook hiphop php vm 实现概述
js 设计模式
参考资料:http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/
一 单例
var SingletonTester = (function(){
// args: an object containing arguments for the singleton // 构造函数在匿名闭包内,所以外部不可见
function Singleton( args ) {
// set args variable to args passed or empty object if none provided.
var args = args || {};
//set the name parameter
this.name = 'SingletonTester';
//set the value of pointX
this.pointX = args.pointX || 6; //get parameter from arguments or set default
//set the value of pointY
this.pointY = args.pointY || 10;
}
// this is our instance holder
var instance;
// this is an emulation of static variables and methods
var _static = {
name: 'SingletonTester',
// This is a method for getting an instance
// It returns a singleton instance of a singleton object
getInstance: function ( args ){
if (instance === undefined) {
instance = new Singleton( args );
}
return instance;
}
};
return _static; // 外部可见的只有这个_static , _static在闭包内定义,所以可以调用构造函数
})();
var singletonTest = SingletonTester.getInstance({pointX: 5});
console.log(singletonTest.pointX); // 输出 5
var anothersSingletonTest = SingletonTester.getInstance({pointX: 66666});
console.log(anothersSingletonTest.pointX); // 输出 5
if (singletonTest === anothersSingletonTest)
console.log('OK');
小结:主要技巧是使用匿名闭包
二 模块化
即js中实现c++中的namespace或者java中的package,
1、基本形式
var basketModule = (function() {
var basket = []; // 私有变量
function doSomethingPrivate(){
//... // 私有函数
}
function doSomethingElsePrivate(){
//...
}
return { // 提供给外部的接口
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
doSomething: doSomethingPrivate(),
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
//basketModule is an object with properties which can also be methods
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
//however, the following will not work:
console.log(basketModule.basket);// 无法访问,其在闭包中
console.log(basket); // 也无法访问
2、jquery中组织库的方法
function library(module) { // 此函数用于定义一个包
$(function() {
if (module.init) {
module.init(); // init是初始化的接口
}
});
return module;
}
var myLibrary = library(function() {
return {
init: function() {
/*implementation*/ // 这里可以对此模块进行初始化
}
};
}());
3、改进
var myRevealingModule = (function(){
var name = 'John Smith';
var age = 40;
function updatePerson(){
name = 'John Smith Updated';
}
function setPerson () {
name = 'John Smith Set';
}
function getPerson () {
return name;
}
return {
set: setPerson, // 此处不再是直接写函数体,而是设个指针
get: getPerson
};
}());
// Sample usage:
myRevealingModule.get();
好处是:return部分的代码更简洁
三 观察者模式
好处:灵活,低耦合、好内聚
坏处:不容易看清楚调用关系(调用栈是从回调处开始的);一个listener挂了,发出消息的对象不知道。
例子:
var pubsub = {};
(function(q) {
var topics = {},
subUid = -1;
// Publish or broadcast events of interest
// with a specific topic name and arguments
// such as the data to pass along
q.publish = function( topic, args ) { // 发布消息
if ( !topics[topic] ) {
return false;
}
setTimeout(function() { // 放到下一个tick里面会安全一点
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args); // 调用回调函数
}
}, 0);
return true;
};
// Subscribe to events of interest
// with a specific topic name and a
// callback function, to be executed
// when the topic/event is observed
q.subscribe = function( topic, func ) { // 注册回调
if (!topics[topic]) {
topics[topic] = [];
}
var token = (++subUid).toString(); // 这个主要是标记各个回调函数
topics[topic].push({
token: token,
func: func
});
return token;
};
// Unsubscribe from a specific
// topic, based on a tokenized reference
// to the subscription
q.unsubscribe = function( token ) {
for ( var m in topics ) {
if ( topics[m] ) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
return token;
}
}
}
}
return false;
};
}( pubsub ));
var testSubscriber = function( topics , data ){
console.log( topics + ": " + data );
};
// 1, 基本使用方法:
// Publishers are in charge of "publishing" notifications about events
pubsub.publish( 'example1', 'hello world!' );
pubsub.publish( 'example1', ['test','a','b','c'] );
pubsub.publish( 'example1', [{'color':'blue'},{'text':'hello'}] );
// Subscribers basically "subscribe" (or listen)
// And once they've been "notified" their callback functions are invoked
var testSubscription = pubsub.subscribe( 'example1', testSubscriber );
// Unsubscribe if you no longer wish to be notified
setTimeout(function(){
pubsub.unsubscribe( testSubscription );
}, 0);
pubsub.publish( 'example1', 'hello again! (this will fail)' );
// 2, 股票交易信息模拟
var grid = {
addEntry: function(data){
if (data !== 'undefined') {
console.log('Entry:'
+ data.title
+ ' Changenet / %'
+ data.changenet
+ '/' + data.percentage + ' % added');
}
},
updateCounter: function(timestamp){
console.log('grid last updated at: ' + timestamp);
}
};
var gridUpdate = function(topics, data){
grid.addEntry(data);
grid.updateCounter(data.timestamp);
}
var gridSubscription = pubsub.subscribe( 'dataUpdated', gridUpdate );
pubsub.publish('dataUpdated', { title: "Microsoft shares", changenet: 4, percentage: 33, timestamp: '17:34:12' });
pubsub.publish('dataUpdated', { title: "Dell shares", changenet: 10, percentage: 20, timestamp: '17:35:16' });
四、中介者模式 The Mediator Pattern
此模式基本概念:把模块之间的网状引用关系,变成一对多的关系,即Mediator负责维护模块间的调用关系。
优点:解耦合、重用
缺点:性能低(不是直接通信)、不容易看清调用流程
与门面模式区别:维护网状依赖, 门面仅仅是简化一个模块的调用。
例子:
var mediator = (function(){
// Subscribe to an event, supply a callback to be executed
// when that event is broadcast
var subscribe = function(channel, fn){
if (!mediator.channels[channel]) mediator.channels[channel] = [];
mediator.channels[channel].push({ context: this, callback: fn });
return this;
},
// Publish/broadcast an event to the rest of the application
publish = function(channel){
if (!mediator.channels[channel]) return false;
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {
var subscription = mediator.channels[channel][i];
subscription.callback.apply(subscription.context, args);
}
return this;
};
return {
channels: {},
publish: publish,
subscribe: subscribe,
installTo: function(obj){
obj.subscribe = subscribe;
obj.publish = publish;
}
};
}());
(function( m ){
function initialize(){
// Set a default value for 'person'
var person = "tim";
// Subscribe to an event called 'nameChange' with
// a callback function which will log the original
// person's name and (if everything works) the new
// name
m.subscribe('nameChange', function( arg ){
console.log( person ); // tim
person = arg;
console.log( person ); // david
});
}
function updateName(){
// Publish/Broadcast the 'nameChange' event with the new data 将原来的直接回调,变成了这样中转一次
m.publish( 'nameChange', 'david' );
}
})( mediator );
五 The Prototype Pattern 原型模式 JS本身就支持
// 所有vehicle都该有的样子
var vehiclePrototype = {
init: function( carModel ) {
this.model = carModel;
},
getModel: function() {
console.log( 'The model of this vehicle is..' + this.model );
}
};
function vehicle( model ) {
function F() {};
F.prototype = vehiclePrototype;
var f = new F();// 这个新对象数据是空的,但是函数却是和vehiclePrototype一样(prototype链机制)
f.init( model );// 将数据进行初始化
return f;
}
var car = vehicle( 'Ford Escort' );
car.getModel();// 调用原型上的函数
六 命令模式
以统一的接口来调用各个函数,JS中函数可以直接当变量传,所以很容易实现
$(function(){
var CarManager = {
// request information
requestInfo: function( model, id ){
return 'The information for ' + model +
' with ID ' + id + ' is foobar';
},
// purchase the car
buyVehicle: function( model, id ){
return 'You have successfully purchased Item '
+ id + ', a ' + model;
},
// arrange a viewing
arrangeViewing: function( model, id ){
return 'You have successfully booked a viewing of '
+ model + ' ( ' + id + ' ) ';
}
};
})();
// 把一个请求映射为具体的函数
CarManager.execute = function( command ){
return CarManager[command.request](command.model,command.carID);
};
// 使用方法
CarManager.execute({request: "arrangeViewing", model: 'Ferrari', carID: '145523'});
CarManager.execute({request: "requestInfo", model: 'Ford Mondeo', carID: '543434'});
CarManager.execute({request: "requestInfo", model: 'Ford Escort', carID: '543434'});
CarManager.execute({request: "buyVehicle", model: 'Ford Escort', carID: '543434'});
七 The DRY Pattern --------相似代码只写一次
1、一般实现
// Let's store some defaults about a car for reference
var defaultSettings = {};
defaultSettings['carModel'] = 'Mercedes';
defaultSettings['carYear'] = 2010;
defaultSettings['carMiles'] = 5000;
defaultSettings['carTint'] = 'Metallic Blue';
// Let's do something with this data if a checkbox is clicked
$('.someCheckbox').click(function(){
if ( this.checked ){
$('#input_carModel').val(activeSettings.carModel);
$('#input_carYear').val(activeSettings.carYear);
$('#input_carMiles').val(activeSettings.carMiles);
$('#input_carTint').val(activeSettings.carTint);
} else {
$('#input_carModel').val('');
$('#input_carYear').val('');
$('#input_carMiles').val('');
$('#input_carTint').val('');
}
});
2、DRY Pattern
$('.someCheckbox').click(function(){
var checked = this.checked,
fields = ['carModel', 'carYear', 'carMiles', 'carTint'];
/*
What are we repeating?
1. input_ precedes each field name
2. accessing the same array for settings
3. repeating value resets
What can we do?
1. programmatically generate the field names
2. access array by key
3. merge this call using terse coding (ie. if checked,
set a value, otherwise don't)
*/
$.each(fields, function(i,key){
$('#input_' + key).val(checked ? defaultSettings[key] : ''); // 这里不是写很多的$('#input_XX').val(activeSettings.YY); 而是统一写一句通用的代码
});
});
3、自己项目中的一段代码实例:
CraftData.inheritsFrom(BasicData);
CraftData.prototype.CRAFT_TYPE_INFO = {
// order is:speed, range, acceleration, maxFuel, weaponNum, maxDamage, maxCapacity, HWPs, costPerMonth
'SKYRANGER' : [760, 13500, 2, 1500, 0, 150, 14, 3, 500000], // 这里的数据没有写成罗嗦的json格式
'INTERCEPTOR' : [2100, 8050, 3, 1000, 2, 100, 0, 0, 600000],
'LIGHTNING' : [3100, 7750, 8, 30, 1, 800, 12, 0, 600000],
'FIRESTORM' : [4200, 7000, 9, 20, 2, 500, 0, 0, 400000],
'AVENGER' : [5400, 27000, 10, 60, 2, 1200, 26, 4, 900000],
};
CraftData.prototype.initSpecialArg = function(){
var that = this;
var arg = that.CRAFT_TYPE_INFO[that.type];
if (!arg){
alert("facility type error! in CraftData.prototype.initSpecialArg ");
throw new error("facility type error! in CraftData.prototype.initSpecialArg ");
}
var order = ['speed', 'range', 'acceleration', 'maxFuel', 'weaponNum', 'maxDamage', 'maxCapacity', 'HWPs', 'costPerMonth'];
for (var index = 0;index < arg.length; index++){
that[order[index]] = arg[index]; // 这里将对应的属性设置上去
}
};
八 门面 The Facade Pattern -----降低使用代码的难度
var module = (function() {
var _private = {
i:5,
get : function() {
console.log('current value:' + this.i);
},
set : function( val ) {
this.i = val;
},
run : function() {
console.log( 'running' );
},
jump: function(){
console.log( 'jumping' );
}
};
return {
facade : function( args ) { // 一次性提供一个facade就好。不使用门面时,需要暴露给client程序员set 和get方法,并且要求client程序员要知道怎么组织这部分的逻辑(先set 后run)
_private.set(args.val);
_private.get();
if ( args.run ) {
_private.run();
}
}
}
}());
module.facade({run: true, val:10});
//outputs current value: 10, running
九 工厂模式
var Car = (function() {
var Car = function ( model, year, miles ){
this.model = model;
this.year = year;
this.miles = miles;
};
return function ( model, year, miles ) {
return new Car( model, year, miles ); // 工厂内部进行new
};
})();
var civic = Car( "Honda Civic", 2009, 20000 ); // 不是直接new 而是调用工厂的方法
var mondeo = Car("Ford Mondeo", 2010, 5000 );
十 The Mixin Pattern 类似于c++的多继承
// Car
var Car = function( settings ){
this.model = settings.model || 'no model provided';
this.colour = settings.colour || 'no colour provided';
};
// Mixin
var Mixin = function(){};
Mixin.prototype = {
driveForward: function(){
console.log('drive forward');
},
driveBackward: function(){
console.log('drive backward');
}
};
// 第一个参数要使用别人功能的对象, 第二个参数 提供功能的对象, 后面的参数是提供的函数的名字
function augment( receivingClass, givingClass ) {
// only provide certain methods
if ( arguments[2] ) {
for (var i=2, len=arguments.length; i<len; i++) {
receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; // 还是使用原型
}
}
// provide all methods
else {
for ( var methodName in givingClass.prototype ) {
/* check to make sure the receiving class doesn't
have a method of the same name as the one currently
being processed */
if ( !receivingClass.prototype[methodName] ) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}
}
// Augment the Car have the methods 'driveForward' and 'driveBackward'*/
augment( Car, Mixin,'driveForward','driveBackward' );
// Create a new Car
var vehicle = new Car({model:'Ford Escort', colour:'blue'});
// Test to make sure we now have access to the methods
vehicle.driveForward(); // 尽管vehicle是car,但是通过augment,使得Car的对象都具有了Mixin的函数
vehicle.driveBackward();
十一 The Decorator Pattern 装饰模式
1、OOP的经典重用技术 -------继承
var subclassExample = subclassExample || {};
subclassExample = {
Person: function( firstName , lastName ){
this.firstName = firstName;
this.lastName = lastName;
this.gender = 'male'
}
}
//a new instance of Person can then easily be created as follows:
var clark = new subclassExample.Person( "Clark" , "Kent" );
//Define a subclass constructor for for 'Superhero':
subclassExample.Superhero = function( firstName, lastName , powers ){
/*
Invoke the superclass constructor on the new object
then use .call() to invoke the constructor as a method of
the object to be initialized.
*/
subclassExample.Person.call(this, firstName, lastName); // 利用js的动态性,实现java中super类似的功能
//Finally, store their powers, a new array of traits not found in a normal 'Person'
this.powers = powers;
}
subclassExample.Superhero.prototype = new subclassExample.Person; // 通过prototype将方法共享过来
var superman = new subclassExample.Superhero( "Clark" ,"Kent" , ['flight','heat-vision'] );
console.log(superman); /* includes superhero props as well as gender*/
2、不用继承 而用装饰者模式 ,java的io流中大量使用了此模式。不使用继承,所以类的层次结构不会被打乱。
//What we're going to decorate
function MacBook() {
this.cost = function () { return 997; };
this.screenSize = function () { return 13.3; };
}
/*Decorator 1*/
function Memory( macbook ) {
var v = macbook.cost();
macbook.cost = function() {
return v + 75; // 这时cost返回的是 997+75
}
}
/*Decorator 2*/
function Engraving( macbook ){
var v = macbook.cost();
macbook.cost = function(){
return v + 200;// 这时cost返回的是 997+75+200
};
}
/*Decorator 3*/
function Insurance( macbook ){
var v = macbook.cost();
macbook.cost = function(){
return v + 250;// 这时cost返回的是 997+75+200+250
};
}
var mb = new MacBook();
Memory(mb);
Engraving(mb);
Insurance(mb);
console.log(mb.cost()); //1522,所以这个值是1522
console.log(mb.screenSize()); //13.3
架构模式
一 MVC
例子:
backbone.js
二 MVP
参考资料:http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/
一 单例
var SingletonTester = (function(){
// args: an object containing arguments for the singleton // 构造函数在匿名闭包内,所以外部不可见
function Singleton( args ) {
// set args variable to args passed or empty object if none provided.
var args = args || {};
//set the name parameter
this.name = 'SingletonTester';
//set the value of pointX
this.pointX = args.pointX || 6; //get parameter from arguments or set default
//set the value of pointY
this.pointY = args.pointY || 10;
}
// this is our instance holder
var instance;
// this is an emulation of static variables and methods
var _static = {
name: 'SingletonTester',
// This is a method for getting an instance
// It returns a singleton instance of a singleton object
getInstance: function ( args ){
if (instance === undefined) {
instance = new Singleton( args );
}
return instance;
}
};
return _static; // 外部可见的只有这个_static , _static在闭包内定义,所以可以调用构造函数
})();
var singletonTest = SingletonTester.getInstance({pointX: 5});
console.log(singletonTest.pointX); // 输出 5
var anothersSingletonTest = SingletonTester.getInstance({pointX: 66666});
console.log(anothersSingletonTest.pointX); // 输出 5
if (singletonTest === anothersSingletonTest)
console.log('OK');
小结:主要技巧是使用匿名闭包
二 模块化
即js中实现c++中的namespace或者java中的package,
1、基本形式
var basketModule = (function() {
var basket = []; // 私有变量
function doSomethingPrivate(){
//... // 私有函数
}
function doSomethingElsePrivate(){
//...
}
return { // 提供给外部的接口
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
doSomething: doSomethingPrivate(),
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
//basketModule is an object with properties which can also be methods
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
//however, the following will not work:
console.log(basketModule.basket);// 无法访问,其在闭包中
console.log(basket); // 也无法访问
2、jquery中组织库的方法
function library(module) { // 此函数用于定义一个包
$(function() {
if (module.init) {
module.init(); // init是初始化的接口
}
});
return module;
}
var myLibrary = library(function() {
return {
init: function() {
/*implementation*/ // 这里可以对此模块进行初始化
}
};
}());
3、改进
var myRevealingModule = (function(){
var name = 'John Smith';
var age = 40;
function updatePerson(){
name = 'John Smith Updated';
}
function setPerson () {
name = 'John Smith Set';
}
function getPerson () {
return name;
}
return {
set: setPerson, // 此处不再是直接写函数体,而是设个指针
get: getPerson
};
}());
// Sample usage:
myRevealingModule.get();
好处是:return部分的代码更简洁
三 观察者模式
好处:灵活,低耦合、好内聚
坏处:不容易看清楚调用关系(调用栈是从回调处开始的);一个listener挂了,发出消息的对象不知道。
例子:
var pubsub = {};
(function(q) {
var topics = {},
subUid = -1;
// Publish or broadcast events of interest
// with a specific topic name and arguments
// such as the data to pass along
q.publish = function( topic, args ) { // 发布消息
if ( !topics[topic] ) {
return false;
}
setTimeout(function() { // 放到下一个tick里面会安全一点
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args); // 调用回调函数
}
}, 0);
return true;
};
// Subscribe to events of interest
// with a specific topic name and a
// callback function, to be executed
// when the topic/event is observed
q.subscribe = function( topic, func ) { // 注册回调
if (!topics[topic]) {
topics[topic] = [];
}
var token = (++subUid).toString(); // 这个主要是标记各个回调函数
topics[topic].push({
token: token,
func: func
});
return token;
};
// Unsubscribe from a specific
// topic, based on a tokenized reference
// to the subscription
q.unsubscribe = function( token ) {
for ( var m in topics ) {
if ( topics[m] ) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1);
return token;
}
}
}
}
return false;
};
}( pubsub ));
var testSubscriber = function( topics , data ){
console.log( topics + ": " + data );
};
// 1, 基本使用方法:
// Publishers are in charge of "publishing" notifications about events
pubsub.publish( 'example1', 'hello world!' );
pubsub.publish( 'example1', ['test','a','b','c'] );
pubsub.publish( 'example1', [{'color':'blue'},{'text':'hello'}] );
// Subscribers basically "subscribe" (or listen)
// And once they've been "notified" their callback functions are invoked
var testSubscription = pubsub.subscribe( 'example1', testSubscriber );
// Unsubscribe if you no longer wish to be notified
setTimeout(function(){
pubsub.unsubscribe( testSubscription );
}, 0);
pubsub.publish( 'example1', 'hello again! (this will fail)' );
// 2, 股票交易信息模拟
var grid = {
addEntry: function(data){
if (data !== 'undefined') {
console.log('Entry:'
+ data.title
+ ' Changenet / %'
+ data.changenet
+ '/' + data.percentage + ' % added');
}
},
updateCounter: function(timestamp){
console.log('grid last updated at: ' + timestamp);
}
};
var gridUpdate = function(topics, data){
grid.addEntry(data);
grid.updateCounter(data.timestamp);
}
var gridSubscription = pubsub.subscribe( 'dataUpdated', gridUpdate );
pubsub.publish('dataUpdated', { title: "Microsoft shares", changenet: 4, percentage: 33, timestamp: '17:34:12' });
pubsub.publish('dataUpdated', { title: "Dell shares", changenet: 10, percentage: 20, timestamp: '17:35:16' });
四、中介者模式 The Mediator Pattern
此模式基本概念:把模块之间的网状引用关系,变成一对多的关系,即Mediator负责维护模块间的调用关系。
优点:解耦合、重用
缺点:性能低(不是直接通信)、不容易看清调用流程
与门面模式区别:维护网状依赖, 门面仅仅是简化一个模块的调用。
例子:
var mediator = (function(){
// Subscribe to an event, supply a callback to be executed
// when that event is broadcast
var subscribe = function(channel, fn){
if (!mediator.channels[channel]) mediator.channels[channel] = [];
mediator.channels[channel].push({ context: this, callback: fn });
return this;
},
// Publish/broadcast an event to the rest of the application
publish = function(channel){
if (!mediator.channels[channel]) return false;
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {
var subscription = mediator.channels[channel][i];
subscription.callback.apply(subscription.context, args);
}
return this;
};
return {
channels: {},
publish: publish,
subscribe: subscribe,
installTo: function(obj){
obj.subscribe = subscribe;
obj.publish = publish;
}
};
}());
(function( m ){
function initialize(){
// Set a default value for 'person'
var person = "tim";
// Subscribe to an event called 'nameChange' with
// a callback function which will log the original
// person's name and (if everything works) the new
// name
m.subscribe('nameChange', function( arg ){
console.log( person ); // tim
person = arg;
console.log( person ); // david
});
}
function updateName(){
// Publish/Broadcast the 'nameChange' event with the new data 将原来的直接回调,变成了这样中转一次
m.publish( 'nameChange', 'david' );
}
})( mediator );
五 The Prototype Pattern 原型模式 JS本身就支持
// 所有vehicle都该有的样子
var vehiclePrototype = {
init: function( carModel ) {
this.model = carModel;
},
getModel: function() {
console.log( 'The model of this vehicle is..' + this.model );
}
};
function vehicle( model ) {
function F() {};
F.prototype = vehiclePrototype;
var f = new F();// 这个新对象数据是空的,但是函数却是和vehiclePrototype一样(prototype链机制)
f.init( model );// 将数据进行初始化
return f;
}
var car = vehicle( 'Ford Escort' );
car.getModel();// 调用原型上的函数
六 命令模式
以统一的接口来调用各个函数,JS中函数可以直接当变量传,所以很容易实现
$(function(){
var CarManager = {
// request information
requestInfo: function( model, id ){
return 'The information for ' + model +
' with ID ' + id + ' is foobar';
},
// purchase the car
buyVehicle: function( model, id ){
return 'You have successfully purchased Item '
+ id + ', a ' + model;
},
// arrange a viewing
arrangeViewing: function( model, id ){
return 'You have successfully booked a viewing of '
+ model + ' ( ' + id + ' ) ';
}
};
})();
// 把一个请求映射为具体的函数
CarManager.execute = function( command ){
return CarManager[command.request](command.model,command.carID);
};
// 使用方法
CarManager.execute({request: "arrangeViewing", model: 'Ferrari', carID: '145523'});
CarManager.execute({request: "requestInfo", model: 'Ford Mondeo', carID: '543434'});
CarManager.execute({request: "requestInfo", model: 'Ford Escort', carID: '543434'});
CarManager.execute({request: "buyVehicle", model: 'Ford Escort', carID: '543434'});
七 The DRY Pattern --------相似代码只写一次
1、一般实现
// Let's store some defaults about a car for reference
var defaultSettings = {};
defaultSettings['carModel'] = 'Mercedes';
defaultSettings['carYear'] = 2010;
defaultSettings['carMiles'] = 5000;
defaultSettings['carTint'] = 'Metallic Blue';
// Let's do something with this data if a checkbox is clicked
$('.someCheckbox').click(function(){
if ( this.checked ){
$('#input_carModel').val(activeSettings.carModel);
$('#input_carYear').val(activeSettings.carYear);
$('#input_carMiles').val(activeSettings.carMiles);
$('#input_carTint').val(activeSettings.carTint);
} else {
$('#input_carModel').val('');
$('#input_carYear').val('');
$('#input_carMiles').val('');
$('#input_carTint').val('');
}
});
2、DRY Pattern
$('.someCheckbox').click(function(){
var checked = this.checked,
fields = ['carModel', 'carYear', 'carMiles', 'carTint'];
/*
What are we repeating?
1. input_ precedes each field name
2. accessing the same array for settings
3. repeating value resets
What can we do?
1. programmatically generate the field names
2. access array by key
3. merge this call using terse coding (ie. if checked,
set a value, otherwise don't)
*/
$.each(fields, function(i,key){
$('#input_' + key).val(checked ? defaultSettings[key] : ''); // 这里不是写很多的$('#input_XX').val(activeSettings.YY); 而是统一写一句通用的代码
});
});
3、自己项目中的一段代码实例:
CraftData.inheritsFrom(BasicData);
CraftData.prototype.CRAFT_TYPE_INFO = {
// order is:speed, range, acceleration, maxFuel, weaponNum, maxDamage, maxCapacity, HWPs, costPerMonth
'SKYRANGER' : [760, 13500, 2, 1500, 0, 150, 14, 3, 500000], // 这里的数据没有写成罗嗦的json格式
'INTERCEPTOR' : [2100, 8050, 3, 1000, 2, 100, 0, 0, 600000],
'LIGHTNING' : [3100, 7750, 8, 30, 1, 800, 12, 0, 600000],
'FIRESTORM' : [4200, 7000, 9, 20, 2, 500, 0, 0, 400000],
'AVENGER' : [5400, 27000, 10, 60, 2, 1200, 26, 4, 900000],
};
CraftData.prototype.initSpecialArg = function(){
var that = this;
var arg = that.CRAFT_TYPE_INFO[that.type];
if (!arg){
alert("facility type error! in CraftData.prototype.initSpecialArg ");
throw new error("facility type error! in CraftData.prototype.initSpecialArg ");
}
var order = ['speed', 'range', 'acceleration', 'maxFuel', 'weaponNum', 'maxDamage', 'maxCapacity', 'HWPs', 'costPerMonth'];
for (var index = 0;index < arg.length; index++){
that[order[index]] = arg[index]; // 这里将对应的属性设置上去
}
};
八 门面 The Facade Pattern -----降低使用代码的难度
var module = (function() {
var _private = {
i:5,
get : function() {
console.log('current value:' + this.i);
},
set : function( val ) {
this.i = val;
},
run : function() {
console.log( 'running' );
},
jump: function(){
console.log( 'jumping' );
}
};
return {
facade : function( args ) { // 一次性提供一个facade就好。不使用门面时,需要暴露给client程序员set 和get方法,并且要求client程序员要知道怎么组织这部分的逻辑(先set 后run)
_private.set(args.val);
_private.get();
if ( args.run ) {
_private.run();
}
}
}
}());
module.facade({run: true, val:10});
//outputs current value: 10, running
九 工厂模式
var Car = (function() {
var Car = function ( model, year, miles ){
this.model = model;
this.year = year;
this.miles = miles;
};
return function ( model, year, miles ) {
return new Car( model, year, miles ); // 工厂内部进行new
};
})();
var civic = Car( "Honda Civic", 2009, 20000 ); // 不是直接new 而是调用工厂的方法
var mondeo = Car("Ford Mondeo", 2010, 5000 );
十 The Mixin Pattern 类似于c++的多继承
// Car
var Car = function( settings ){
this.model = settings.model || 'no model provided';
this.colour = settings.colour || 'no colour provided';
};
// Mixin
var Mixin = function(){};
Mixin.prototype = {
driveForward: function(){
console.log('drive forward');
},
driveBackward: function(){
console.log('drive backward');
}
};
// 第一个参数要使用别人功能的对象, 第二个参数 提供功能的对象, 后面的参数是提供的函数的名字
function augment( receivingClass, givingClass ) {
// only provide certain methods
if ( arguments[2] ) {
for (var i=2, len=arguments.length; i<len; i++) {
receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; // 还是使用原型
}
}
// provide all methods
else {
for ( var methodName in givingClass.prototype ) {
/* check to make sure the receiving class doesn't
have a method of the same name as the one currently
being processed */
if ( !receivingClass.prototype[methodName] ) {
receivingClass.prototype[methodName] = givingClass.prototype[methodName];
}
}
}
}
// Augment the Car have the methods 'driveForward' and 'driveBackward'*/
augment( Car, Mixin,'driveForward','driveBackward' );
// Create a new Car
var vehicle = new Car({model:'Ford Escort', colour:'blue'});
// Test to make sure we now have access to the methods
vehicle.driveForward(); // 尽管vehicle是car,但是通过augment,使得Car的对象都具有了Mixin的函数
vehicle.driveBackward();
十一 The Decorator Pattern 装饰模式
1、OOP的经典重用技术 -------继承
var subclassExample = subclassExample || {};
subclassExample = {
Person: function( firstName , lastName ){
this.firstName = firstName;
this.lastName = lastName;
this.gender = 'male'
}
}
//a new instance of Person can then easily be created as follows:
var clark = new subclassExample.Person( "Clark" , "Kent" );
//Define a subclass constructor for for 'Superhero':
subclassExample.Superhero = function( firstName, lastName , powers ){
/*
Invoke the superclass constructor on the new object
then use .call() to invoke the constructor as a method of
the object to be initialized.
*/
subclassExample.Person.call(this, firstName, lastName); // 利用js的动态性,实现java中super类似的功能
//Finally, store their powers, a new array of traits not found in a normal 'Person'
this.powers = powers;
}
subclassExample.Superhero.prototype = new subclassExample.Person; // 通过prototype将方法共享过来
var superman = new subclassExample.Superhero( "Clark" ,"Kent" , ['flight','heat-vision'] );
console.log(superman); /* includes superhero props as well as gender*/
2、不用继承 而用装饰者模式 ,java的io流中大量使用了此模式。不使用继承,所以类的层次结构不会被打乱。
//What we're going to decorate
function MacBook() {
this.cost = function () { return 997; };
this.screenSize = function () { return 13.3; };
}
/*Decorator 1*/
function Memory( macbook ) {
var v = macbook.cost();
macbook.cost = function() {
return v + 75; // 这时cost返回的是 997+75
}
}
/*Decorator 2*/
function Engraving( macbook ){
var v = macbook.cost();
macbook.cost = function(){
return v + 200;// 这时cost返回的是 997+75+200
};
}
/*Decorator 3*/
function Insurance( macbook ){
var v = macbook.cost();
macbook.cost = function(){
return v + 250;// 这时cost返回的是 997+75+200+250
};
}
var mb = new MacBook();
Memory(mb);
Engraving(mb);
Insurance(mb);
console.log(mb.cost()); //1522,所以这个值是1522
console.log(mb.screenSize()); //13.3
架构模式
一 MVC
例子:
backbone.js
二 MVP
发表评论
-
camunda 源代码解析(一)
2020-03-06 17:53 2997壹 基本概念 一、任 ... -
spring cloud gateway 分析一 主流程和层次
2020-02-14 19:27 559一、debug的调用栈如下: DispatcherHand ... -
B端产品学习笔记
2018-12-01 22:25 805B端产品学习笔记 一、B端产品分类:协作办公 即时通讯 企 ... -
大数据、数据仓库和ETL
2018-07-27 20:50 4387一、背景 大量原来线下的业务电子化之后,产生了 ... -
单机与分布式的组件差异
2018-07-25 15:51 710一、单机程序 1、用内存进程队列实现解耦合和异步 ... -
大数据数据仓库 《大数据之路:阿里巴巴大数据实践》 读书笔记
2018-07-17 18:11 857一、基本概念 1 ... -
ElasticSearch 三 建立索引快的原因
2018-07-09 18:02 835https://blog.csdn.net/u010994 ... -
ElasticSearch 二 查询快的原因
2018-07-09 17:25 2463https://www.jianshu.com/p/ ... -
ElasticSearch 一 基本概念
2018-07-09 17:22 5051、Indices 索引,类似于mysql的Database ... -
后端技术的演化
2018-01-05 18:04 559一、应用分类: 数据库交易类、数据处理(大数据、机器学习、 ... -
pandas 小技巧
2018-01-05 17:34 5911、筛选数据 complaints[['Complaint ... -
深度学习思考和理解 一 统计学和信息论
2017-09-18 11:00 8671、世界是不确定的,所有的函数表达式y=f(x) 只在理论中 ... -
基于camunda的工作流开发
2017-07-11 09:21 14880一、定义 工作流(Wor ... -
数据挖掘概览
2017-06-30 17:22 573数据、信息、知识、智 ... -
服务端相关技术总结
2017-06-16 10:38 434服务端相关技术总结 在实际产品中,主要涉及到的计算 ... -
django源代码解析
2017-06-08 11:12 908一、wsgi: webserver与app ... -
web开发java VS python
2017-06-07 17:38 1097一、基本概念和知识点 1、web server:实现了ht ... -
spring4系列二 spring boot 解析
2017-05-15 17:42 5261、基本概念 Environment 系统环境变量、jv ... -
spring4 系列一 概览
2017-05-03 14:28 517零、前言 java是静态类型语言,为了能达到动态类型语言的 ... -
Dubbo源代码解析
2017-04-26 16:36 541一、Dubbo源代码层次结 ...
相关推荐
"JavaScript设计模式与开发实践.pdf" 本书《JavaScript设计模式与开发实践》是JavaScript语言的设计模式和开发实践的指南,旨在帮助初、中、高级Web前端开发人员和想往架构师晋级的中高级程序员,掌握JavaScript...
JavaScript设计模式.pdf JavaScript设计模式是指在软件开发中使用JavaScript语言编写的设计模式。这些设计模式旨在提高代码的重用性、可读性、维护性和扩展性。以下是JavaScript设计模式的知识点总结: 1. 单体...
JavaScript设计模式是编程实践中一种重要的思想,它通过总结和提炼出...阅读提供的文件如"JavaScript设计模式8.pdf"、"JavaScript设计模式1.pdf"和"xunzai[1].com_js设计模式+源码.rar",将深入探讨更多细节和实例。
《JavaScript设计模式》是JavaScript设计模式的学习指南。全书分为14章。首先介绍了什么是模式、模式的结构、类别、模式的分类、如何编写模式等等;然后,集中介绍了很多流行的设计模式在JavaScript中的应用,包括...
JavaScript设计模式与开发实践是深入理解并提升JavaScript编程能力的关键领域。设计模式是对在软件设计中经常出现的问题的解决方案的描述,它代表了最佳实践,是经验丰富的开发者们经过时间检验后总结出来的解决常见...
JavaScript设计模式是由张容铭编著的一本关于JavaScript编程领域的重要参考书籍,主要探讨了如何在JavaScript编程中应用设计模式来提升代码质量和可维护性。设计模式是软件工程中的最佳实践,它们是针对常见问题的...
《JavaScript设计模式》中,Google和Yahoo公司的两位资深Web专家对此给出了掷地有声的肯定回答。作者针对常见的开发任务,从YUI等实战代码中取材,提供了专家级的解决方案,不仅透彻剖析了JavaScript扣的面向对象...
1. **JavaScript设计模式**: 设计模式是软件工程中经过实践验证的、解决常见问题的有效方法。在JavaScript中,常见的设计模式包括: - 单例模式:确保一个类只有一个实例,并提供全局访问点。 - 工厂模式:创建...
### JavaScript设计模式与开发实践 #### 一、引言 在软件工程领域,设计模式是一种在特定场景下解决常见问题的可复用解决方案。对于JavaScript这样的动态语言来说,设计模式的应用更加灵活多变,同时也更加重要。...
#### 一、JavaScript设计模式的概念与起源 - **设计模式起源**:设计模式最初来源于建筑学领域,建筑师Christopher Alexander提出的“模式语言”概念,旨在解决建筑设计中的常见问题。随后,这一理念被引入到软件...
外文翻译:学用JavaScript设计模式,pdf版本,中文版 设计模式是可重用的用于解决软件设计中一般问题的方案。设计模式如此让人着迷,以至在任何编程语言中都有对其进行的探索。 其中一个原因是它可以让我们站在巨人...
书中不仅介绍了JavaScript中经典和现代的设计模式,还包括了针对不同JavaScript开发框架(如MVC、MVP、MVVM)的设计模式,以及最新的模块化JavaScript设计模式(AMD、CommonJS、ES Harmony)和jQuery中的设计模式。...
JavaScript 设计模式概述 JavaScript 设计模式是一个非常重要的概念,在前端开发中,掌握设计模式可以提高开发效率和代码质量。本文将对 JavaScript 设计模式进行总体介绍,并对闭包、封装等重要概念进行详细讲解。...
因此,通过学习JavaScript设计模式,Web开发人员能够更好地组织代码,写出更加健壮且易于维护的JavaScript应用程序。 《Javascript 设计模式》电子书深入讲解了JavaScript开发原理以及在客户端脚本开发中的设计模式...
在吃透了前面所说的书之后,接下来两本书的顺序已经无关紧要了,《JavaScript DOM高级程序设计》(注意和《JavaScript 高级程序设计》相区别)和《JavaScript设计模式》,这两本都是重量级的书,能让你的JS技术上一...
JavaScript设计模式详解与函数式编程是开发者提升代码质量和可维护性的重要工具。设计模式是对在软件设计中经常出现的问题和解决方案的一种模式化描述,而函数式编程则是一种编程范式,强调程序数据的不可变性和函数...
为了帮助大家快速和较好地理解JavaScript设计模式中的单例模式,本文对JavaScript的单例模式进行了分析并进行简易的代码演示,希望本文能够给有需要的人带来一点小小的帮助。
### 外文翻译:学用JavaScript设计模式 #### 序言与重要性 设计模式作为软件工程中的一个重要组成部分,其核心在于提供了一套标准的方法论,帮助开发人员以优雅、高效的方式解决常见的软件设计问题。《学用...
### JavaScript设计模式经典知识点概述 #### 一、书籍简介与背景 《Pro JavaScript Design Patterns》是一本关于JavaScript设计模式的经典著作,由Ross Harmes和Dustin Diaz共同编写,并于2008年出版。该书深入浅出...