- 浏览: 245005 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
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 3119壹 基本概念 一、任 ... -
spring cloud gateway 分析一 主流程和层次
2020-02-14 19:27 570一、debug的调用栈如下: DispatcherHand ... -
B端产品学习笔记
2018-12-01 22:25 817B端产品学习笔记 一、B端产品分类:协作办公 即时通讯 企 ... -
大数据、数据仓库和ETL
2018-07-27 20:50 4399一、背景 大量原来线下的业务电子化之后,产生了 ... -
单机与分布式的组件差异
2018-07-25 15:51 722一、单机程序 1、用内存进程队列实现解耦合和异步 ... -
大数据数据仓库 《大数据之路:阿里巴巴大数据实践》 读书笔记
2018-07-17 18:11 869一、基本概念 1 ... -
ElasticSearch 三 建立索引快的原因
2018-07-09 18:02 844https://blog.csdn.net/u010994 ... -
ElasticSearch 二 查询快的原因
2018-07-09 17:25 2490https://www.jianshu.com/p/ ... -
ElasticSearch 一 基本概念
2018-07-09 17:22 5181、Indices 索引,类似于mysql的Database ... -
后端技术的演化
2018-01-05 18:04 572一、应用分类: 数据库交易类、数据处理(大数据、机器学习、 ... -
pandas 小技巧
2018-01-05 17:34 6001、筛选数据 complaints[['Complaint ... -
深度学习思考和理解 一 统计学和信息论
2017-09-18 11:00 8761、世界是不确定的,所有的函数表达式y=f(x) 只在理论中 ... -
基于camunda的工作流开发
2017-07-11 09:21 14945一、定义 工作流(Wor ... -
数据挖掘概览
2017-06-30 17:22 580数据、信息、知识、智 ... -
服务端相关技术总结
2017-06-16 10:38 447服务端相关技术总结 在实际产品中,主要涉及到的计算 ... -
django源代码解析
2017-06-08 11:12 919一、wsgi: webserver与app ... -
web开发java VS python
2017-06-07 17:38 1110一、基本概念和知识点 1、web server:实现了ht ... -
spring4系列二 spring boot 解析
2017-05-15 17:42 5381、基本概念 Environment 系统环境变量、jv ... -
spring4 系列一 概览
2017-05-03 14:28 534零、前言 java是静态类型语言,为了能达到动态类型语言的 ... -
Dubbo源代码解析
2017-04-26 16:36 560一、Dubbo源代码层次结 ...
相关推荐
"JavaScript设计模式与开发实践.pdf" 本书《JavaScript设计模式与开发实践》是JavaScript语言的设计模式和开发实践的指南,旨在帮助初、中、高级Web前端开发人员和想往架构师晋级的中高级程序员,掌握JavaScript...
JavaScript设计模式.pdf JavaScript设计模式是指在软件开发中使用JavaScript语言编写的设计模式。这些设计模式旨在提高代码的重用性、可读性、维护性和扩展性。以下是JavaScript设计模式的知识点总结: 1. 单体...
JavaScript设计模式与开发实践是深入理解并提升JavaScript编程能力的关键领域。设计模式是对在软件设计中经常出现的问题的解决方案的描述,它代表了最佳实践,是经验丰富的开发者们经过时间检验后总结出来的解决常见...
#### 一、JavaScript设计模式的概念与起源 - **设计模式起源**:设计模式最初来源于建筑学领域,建筑师Christopher Alexander提出的“模式语言”概念,旨在解决建筑设计中的常见问题。随后,这一理念被引入到软件...
外文翻译:学用JavaScript设计模式,pdf版本,中文版 设计模式是可重用的用于解决软件设计中一般问题的方案。设计模式如此让人着迷,以至在任何编程语言中都有对其进行的探索。 其中一个原因是它可以让我们站在巨人...
JavaScript设计模式详解与函数式编程是开发者提升代码质量和可维护性的重要工具。设计模式是对在软件设计中经常出现的问题和解决方案的一种模式化描述,而函数式编程则是一种编程范式,强调程序数据的不可变性和函数...
在现代前端开发中,JavaScript设计模式已经成为了一门必修课程。它不仅能够提升开发者的编码效率,而且还能保证编写的代码更加健壮、可维护。本文将对JavaScript设计模式的核心概念进行深入探讨,以期帮助开发者更好...
### Node.js设计模式第二版概览 #### 一、书籍基本信息 - **书名**:《Node.js设计模式》第二版 - **作者**:Mario Casciaro 和 Luciano Mammino - **出版社**:Packt Publishing - **出版时间**:第二版于2016年7...
在这个"js设计模式.rar"压缩包中,我们可能会发现一系列关于JavaScript设计模式的文档或代码示例。 设计模式可以分为三大类:创建型、结构型和行为型。下面将详细介绍这三类中的主要设计模式,并结合JavaScript的...
面向对象编程(Object-Oriented Programming, OOP)是JavaScript中的核心概念,而设计模式则是解决常见编程问题的经验总结,对于提升代码质量和可维护性至关重要。这两本书——"JavaScript 面向对象编程.pdf"和...
在深入探讨《JavaScript设计模式系统讲解与应用》的内容之前,我们先来了解一下设计模式的基本概念以及为什么它对于前端开发人员尤为重要。设计模式是一套被反复使用的、经过分类编目的、包含结构化的解决方案,用于...
JavaScript设计模式是编程实践中的一种重要思想,它提供了一套经过时间考验的最佳实践,用来解决常见的编程问题和提高代码的可维护性、可扩展性和可复用性。在JavaScript这种动态类型的脚本语言中,设计模式尤其重要...
JavaScript设计模式是软件开发中的一种最佳实践,它总结了在解决特定问题时,代码组织和交互的常见方式。这些模式可以帮助开发者编写可维护、可扩展、易于理解和复用的代码。"js-design-pattern"这个主题涵盖了...
JavaScript设计模式是软件开发中的一种最佳实践,它们提供了一种在特定情况下解决复杂问题的标准化方法。本笔记和代码集合涵盖了多种重要的设计模式,旨在帮助开发者编写更可维护、可扩展和可重用的JavaScript代码。...
### Node.js设计模式第二版 #### 一、概述 《Node.js Design Patterns Second Edition》(Node.js设计模式第二版)是一本深入探讨Node.js高级编程技术的书籍,它旨在帮助开发者充分利用Node.js的强大功能和最佳...
包括面向对象,面向对象编程思想,javascript面向对象,设计模式通俗版,快速进入模式学习与实践。
Javascript 设计模式系统讲解与应用视频资源地址.txt