单例模式

何为单例模式,就是无论执行多少次函数,都只会生成一个对象哈哈,看一个简单的demo

function Instance(name) {
this.name = name;
} Instance.prototype.fire = function () {
console.log(this.name);
} var singleton = (function () {
var instance = null;
return function (name) {
if (!instance)
instance = new Instance(name);
return instance;
}
})();
singleton('dqhan').fire();
singleton('dqhan1').fire();

通过闭包形式保存一个对象instance,然后每次判断该对象是否存在,如果存在就直接返回该对象

如果我们要改变这个对象的内部属性呢,添加一个扩展方法即可

function Instance(name) {
this.name = name;
} Instance.prototype.fire = function () {
console.log(this.name);
} Instance.prototype.set = function (name) {
this.name = name;
} var singleton = (function () {
var instance = null;
return function (name) {
if (!instance)
instance = new Instance(name);
else
instance.set(name);
return instance;
}
})();
singleton('dqhan').fire();
singleton('dqhan1').fire();

但是并不满足设计模式中的单一职责原则,对象与单例模式过于耦合,我们考虑仅提供单例模式创建对象,具体对象由外部设置

var singleton = function (fn) {
var instance = null;
return function () {
if (!instance) instance = fn.apply(this, arguments)
return instance;
}
}
//对外暴露部分 var setSingleton = singleton(function () {
var instance = new Instance('dqhan');
return instance;
}) function Instance(name) {
this.name = name;
} Instance.prototype.fire = function () {
console.log(this.name);
} Instance.prototype.set = function (name) {
this.name = name;
}
 setSingleton('dqhan').fire();
  setSingleton('dqhan1').fire();

工厂模式

工厂模式是指创造一些目标的方法模式,工厂模式分为简单工厂模式,复杂工厂模式,抽象工厂模式

简单工厂

function Factory(name) {
this.name = name;
} Factory.prototype.changeName = function (name) {
this.name = name;
} var demo = new Factory('dqhan');
var demo1 = new Factory('dqhan1');

看上去是不是一个构造函数呢,没错构造函数也是工厂模式,当然这只是个工厂模式的雏形,下面我们看一个严格意义上的简单工厂模式

function Factory(type) {
function Cat() {
this.name = 'cat';
} Cat.prototype.say = function () {
console.log('miaomiao~');
} function Dog() {
this.name = 'dog';
} Dog.prototype.say = function () {
console.log('wangwang~');
} var alr = {
cat: function () {
return new Cat();
},
dog: function () {
return new Dog();
}
}; this.__proto__ = alr[type]();
} var cat = new Factory('cat');
cat.say();
var dog = new Factory('dog');
dog.say();

根据type生成目标对象,我们在回想一下工厂模式得核心思想,工厂模式要求创建对象得活交给字类去做,我们是不是可以在改进一下

function Factory(type) {
return new this[type]();
} Factory.prototype = {
Cat: function () {
this.name = 'cat';
this.__proto__.say = function () {
console.log('miaomiao~');
}
},
Dog: function () {
this.name = 'dog';
this.__proto__.say = function () {
console.log('wangwang~');
}
}
} var cat = new Factory('Cat');
cat.say();
var dog = new Factory('Dog');
dog.say();

我们讲创建子类得方法添加到工厂方法得原型上,让子类单独成为了一个构造函数,到目前为止,我们可以再想想,每次创建对象我们都需要new一个工厂方法,这样对外暴是不是很不友好,我们可以不可以直接调用工厂方法呢,没错,我们采用

安全模式创建实例

function Factory(type) {
if (this instanceof Factory)
return new this[type]();
else
return new Factory(type);
} Factory.prototype = {
Cat: function () {
this.name = 'cat';
this.__proto__.say = function () {
console.log('miaomiao~');
}
},
Dog: function () {
this.name = 'dog';
this.__proto__.say = function () {
console.log('wangwang~');
}
}
} var cat = Factory('Cat');
cat.say();
var dog = new Factory('Dog');
dog.say();

这样做有什么好处呢,我们可以兼容new一个对象或者直接调用方法创建一个对象,于是乎我们联想到了什么,是不是大名鼎鼎得jquery呢,jquery就是一个非常典型得工厂模式啊,我们来采取jquery源码得方式实现一个

function Factory(type) {
return new Factory.fn.init(type);
} var fn = {
init: function (type) {
//当前this指向fn对象
var target = this[type]();
return target;
}
} Factory.fn = fn; Factory.prototype.init = function (type) {
var target = this[type]();
return target;
}
Factory.prototype = {
Cat: function () {
this.name = 'cat';
this.__proto__.say = function () {
console.log('miaomiao~');
}
},
Dog: function () {
this.name = 'dog';
this.__proto__.say = function () {
console.log('wangwang~');
}
}
}
/**
* 改变上面init中this指向问题使this指向Factory
*/
Factory.fn.init.prototype = Factory.prototype; var cat = Factory('Cat');
cat.say();
var dog = new Factory('Dog');
dog.say();

简单工厂模式跟常规工厂模式都是直接创建实例,但是如果遇到复杂场景,这里就需要采用抽象工厂模式,抽象工厂模式不是创建一个实例,而是创建一个集合,这个集合包含很多情况,每个情况可以使用具体实例

本质上抽象工厂就是子类继承父类的方法

抽象工厂

function AbstractFactory(fType) {
if (this instanceof AbstractFactory) {
ChildrenFn.prototype = new this[fType]();
} else
return new AbstractFactory(fType, ChildrenFn);
} AbstractFactory.prototype.Cat = function () {
this.name = 'cat';
} AbstractFactory.prototype.Cat.prototype = {
say: function () {
console.log('miaomiao~');
}
} AbstractFactory.prototype.Dog = function () {
this.name = 'dog';
} AbstractFactory.prototype.Dog.prototype = {
say: function () {
console.log('wangwang~')
}
}
//抽象工厂方法提供得接口不允许调用,需要字类重写,所以我们要加个限制 function AbstractFactory(fType, ChildrenFn) {
if (this instanceof AbstractFactory) {
ChildrenFn.prototype = new this[fType]();
} else
return new AbstractFactory(fType, ChildrenFn);
} AbstractFactory.prototype.Cat = function () {
this.name = 'cat';
} AbstractFactory.prototype.Cat.prototype = {
say: function () {
throw new Error('不允许效用,仅允许重写。')
console.log('miaomiao~');
}
} AbstractFactory.prototype.Dog = function () {
this.name = 'dog';
} AbstractFactory.prototype.Dog.prototype = {
say: function () {
throw new Error('不允许效用,仅允许重写。')
console.log('wangwang~')
}
} function 美短Cat(name) {
this.type = '美短';
this.name = name;
} AbstractFactory('Cat', 美短Cat) var CatA = new 美短Cat('A'); // CatA.say(); AbstractFactory('Cat', 暹罗Cat) function 暹罗Cat(name) {
this.type = '暹罗';
this.name = name
this.__proto__.say = function () {
console.log('重写cat say');
}
} var CatB = new 暹罗Cat('B'); CatB.say();

好了,到目前位置,是不是了解了工厂模式呢

策略模式

什么是策略模式,就是分情况处理嘛,符合A得调用处理A得方法,符合B得调用B处理方法

我们平时写代码经常写的总归是if else嘛。简单写个demo

function fn(type) {
if (type === 1)
(function () {
console.log('1');
})();
if (type === 2)
(function () {
console.log('2');
})()
if (type === 3)
(function () {
console.log('3')
})()
} fn(1);
fn(2);
fn(3);

这样写导致什么问题呢,是不是当我们增加新的情况得时候,要不停得添加if判断,或者在好点,我们干脆就用switch好了,是不是给人得感觉狠乱,很不直观,如果采用策略模式呢

var map = {
1: fn1,
2: fn2,
3: fn3
}
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
function fn3() {
console.log(3);
}
function fn(type) {
map[type]();
}

这样写出来是不是就很直观了,当有复杂情况得时候我们可以提供一个额外得command方法来增加

function extendCommend(type, fn) {
map[type] = fn;
}

好了这就是策略模式

代理模式

什么是代理模式,简单得来讲,就是增加一个额外得壳子,代理分了三种,保护代理,虚拟代理,缓存代理 下面我们看下这三种代理究竟是怎么回事儿吧

保护代理

function targetAction(props) {
console.dir(props);
}
//现在我们要求不是所有的情况都可以条用这个方法,添加保护代理 function proxyTargetAction(props) {
if (typeof props === 'string') console.log('拒绝使用目标函数')
targetAction(props);
}
proxyTargetAction({ name: 'dqhan' });
proxyTargetAction('str');

我们在原方法上添加一个壳子,对外暴露得是这个壳子方法,对传入参数进行保护

虚拟代理

其实虚拟代理我们平时是总会用到的,那就是函数节流与防抖了~下面我就就实现一个吧

function debounce(fn, delay) {
var self = this,
timer;
return function () {
clearInterval(timer);
timer = setTimeout(function () {
fn.apply(self, arguments);
}, delay)
}
}

缓存代理

function add() {
var arg = [].slice.call(arguments); return arg.reduce(function (a, b) {
return a + b;
});
} // 代理
var proxyAdd = (function () {
var cache = {}; return function () {
var arg = [].slice.call(arguments).join(',');
// 如果有,则直接从缓存返回
if (cache[arg]) {
return cache[arg];
} else {
var result = add.apply(this, arguments);
cache[arg] = result;
return result;
}
};
})();
proxyAdd(1, 2, 3, 4, 5);
proxyAdd(1, 2, 3, 4, 5);//直接从缓存中输出

我们利用闭包形式缓存一快空间,然后当参数相同一致得时候便不再执行函数,而是缓存读取这个值

观察者模式

观察者模式又称发布订阅模式,这种设计模式最大得特点就是整个程序采用了事件驱动得方式来执行

想象一下,React中两个平级组件如何通信呢,是不是通过父级组件呢,如果是两个模块呢,没有了父组件怎么办呢,我们就可以采用这种设计模式来实现

var observer = (function () {
var events = {};
return function () {
return {
register: function (eventName, callback) {
events[eventName] = callback;
},
fire: function (eventName) {
if (toString.call(events[eventName]) !== '[object Function]')
throw new Error('error');
else
return events[eventName]();
},
remove: function (eventName) {
if (toString.call(events[eventName]) !== '[object Function]')
throw new Error('error');
else
delete events[eventName];
}
}
}
})(); var ob = observer();
ob.register('say', function () {
console.log('demo');
}); ob.fire('say'); // ob.remove('say');

装饰者模式

以动态方式对某个对象添加一些额外得职能,但是不影响该对象以及对象得衍生物

function Demo() {

}
Demo.prototype.fire = function () {
console.log('fire');
} var demo = new Demo(); //装饰器
function Decorator(demo) {
this.demo = demo;
} Decorator.prototype.fire = function () {
this.demo.fire();
} var cat = new Decorator(demo); cat.fire();

其实我们很多时候可以利用这种设计模式,比如架构层面得当我们使用了第三方得控件以满足我们自己得需求时候,这也算宏观得装饰者模式

再比如我们自己封装一个控件得时候,如果我们想要多个web框架进行迁移或者兼容得时候我们也可以这么做,看个我自己封装得控件demo吧

控件主体部分

(function (global,
$,
$$,
factory,
plugin) {
if (typeof global[plugin] !== "object") global[plugin] = {};
$.extend(true, global[plugin], factory.call(global, $, $$))
})(window, $, $$, function (
$,
$$
) {
var uuid = -1;
var _TabControl = function (ops) {
this._ops = {
items: ops.items || [],
hashItems: {},
selectedIndex: ops.selectedIndex || 0
};
this._element = $(ops.element);
this._tabContainerId = "ui-tabcontrol-container-";
this._oldValue = { selectedIndex: 0 };
this._convertHashItems();
this._init()
._initId()
._create()
._initMember()
._setTabContainer()
._setTabContent()
._bindEvent();
}; _TabControl.prototype = {//...省略了
}
return {
TabControl: _TabControl
}
}, "ui")

React壳子

import ReactWidget from './react-widget';

class TabControl extends ReactWidget {
constructor(props) {
super(props);
} componentWillReceiveProps(newProps) {
this.element.setOptions({
items: newProps.items,
selectedIndex: newProps.selectedIndex
});
} componentDidMount() {
this.element = new ui.TabControl({
element: ReactDOM.findDOMNode(this),
items: this.props.items,
selectedIndex: this.props.selectedIndex
});
$(ReactDOM.findDOMNode(this)).on('tabHandleChanged', this.props.selectChanged.bind(this));
} render() {
return <div>
<div className='ui-tabcontrol-content'>
{this.props.children}
</div>
</div>
}
} window.$$.TabControl = TabControl;

当我们使用vue的时候,只需要将react壳子换成vue就行了

外观模式

所谓的外观模式,就是将核心的方法打包成一个方法暴漏给外围模块

function add() {
console.log('add');
} function delete1() {
console.log('delete');
} function multiplication() {
console.log('multiplication');
} function division() {
console.log('division')
} function execute() {
add();
delete1();
multiplication();
division();
} execute();

适配器模式

适配器模式核心思想就是兼容不同情况,其实这种方式同样可以使用在框架兼容方面

function add(props) {
if (toString.call(props) === '[object Object]') {
var arr = [];
for (var i in props) {
if (props.hasOwnProperty(i))
arr.push(props[i]);
}
return arr.reduce(function (pre, next) {
return pre + next;
})
}
if (toString.call(props) === '[object Array]') {
return props.reduce(function (pre, next) {
return pre + next;
})
} throw new Error('paramster is error.')
} add([1, 2, 3]);
add({ a: 1, d: 2, c: 3 })

享元模式

享元模式是一种性能优化,核心思想是运用共享技术来实现大量细粒度对象的创建,我们来见识下吧

function Person(props) {
this.name = props.name;
this.sex = props.sex;
this.height = props.height;
this.weight = props.weight;
} Person.prototype.info = function () {
console.log(this.name + this.sex + this.height + this.weight);
} var metadata = [
{ name: 'dqhan0', sex: 'male', height: '170cm', weight: '125kg' },
{ name: 'dqhan1', sex: 'female', height: '165cm', weight: '135kg' },
{ name: 'dqhan2', sex: 'male', height: '180cm', weight: '145kg' },
{ name: 'dqhan3', sex: 'male', height: '173cm', weight: '155kg' },
{ name: 'dqhan4', sex: 'female', height: '169cm', weight: '165kg' },
{ name: 'dqhan5', sex: 'male', height: '168cm', weight: '175kg' },
] function execute() {
metadata.forEach(m => {
new Person(m).info();
})
} execute();

上面的例子我们可以看出来new出来了6个对象,当程序员的都知道new的过程就是在内存空间开辟内存的过程,如果成千上万个对象呢,是不是内存就炸了,我们利用享元模式优化一下

从上面例子我们可以看出,其实person的性别只有男女,我们就抽离这个男女当作享元

function Person(sex) {
this.sex = sex;
this.name = '';
this.height = '';
this.weight = '';
} Person.prototype.info = function () {
console.log(this.name + this.sex + this.height + this.weight);
} var male = new Person('male');
var female = new Person('female'); function execute() {
metadata.forEach(m => {
if (m.sex === 'male') {
male.name = m.name;
male.height = m.height;
male.weight = m.weight;
male.info();
} else {
female.name = m.name;
female.height = m.height;
female.weight = m.weight;
female.info();
}
})
}
execute();

代码实现抽离,但是看起来耦合是不是很高啊,我们在改进一下

批量创建对象,我们想到了什么设计模式,没错工厂模式,好了我们就用工厂模式优化

function Person(sex) {
this.sex = sex;
console.log('create person');
} Person.prototype.info = function (name) {
ManagerPeson.setExternalState(name, this);
console.log(this.name + this.sex + this.height + this.weight);
} var PersonFactory = (function () {
var pool = {};
return function (sex) {
if (pool[sex]) { }
else {
pool[sex] = new Person(sex);
}
return pool[sex];
}
})(); var ManagerPeson = (function () {
var pool = {};
return function () {
return {
add: function (m) {
if (pool[m.name]) {
} else {
pool[m.name] = {
name: m.name,
height: m.height,
weight: m.weight
};
}
return PersonFactory(m.sex);
},
setExternalState(name, target) {
var poolTarget = pool[name];
for (var i in poolTarget) {
if (poolTarget.hasOwnProperty(i))
target[i] = poolTarget[i]
}
}
}
}
})() function execute() {
metadata.forEach(m => {
ManagerPeson.add(m).info(m.name);
})
}

这里由三部分组成,首先是目标对象person,然后工厂模式创建对象,通过性别来决定是否创建新的对象,当然为了缓存享元,我们采用了闭包,最后我们通过MangerPerson整合每个person的特有属性

命令模式

一种松耦合的设计思想,使发送者与接收者消除彼此之前得耦合关系

html

<button id="refresh">refresh</button>
<button id="add">add</button>
<button id="del">delete</button>

我们来对这三个button进行绑定式优化

传统模式

refreshBtn.addEventListener('click', function () {
console.log('refresh');
}) addBtn.addEventListener('click', function () {
console.log('add');
}) delBtn.addEventListener('click', function () {
console.log('delete')
})
    var Refresh = function () {

    }

    Refresh.prototype.action = function () {
console.log('refresh')
} var Add = function () { } Add.prototype.action = function () {
console.log('add')
} var Del = function () { } Del.prototype.action = function () {
console.log('delete')
} var RefreshCommand = function (receiver) {
return {
excute() {
receiver.action();
}
}
} var AddCommand = function (receiver) {
return {
excute() {
receiver.action();
}
}
} var DeleteCommand = function (receiver) {
return {
name: 'delete command',
excute() {
receiver.action();
}
}
} var setCommand = function (btn, command) {
console.dir(command);
btn.addEventListener('click', function () {
command.excute();
})
} var refreshCommand = RefreshCommand(new Refresh());
var addCommand = AddCommand(new Add());
var delCommand = DeleteCommand(new Del());
setCommand(refreshBtn, refreshCommand)
setCommand(addBtn, addCommand)
setCommand(delBtn, delCommand)

命令模式规定一个命令要有执行函数excute,场景复杂可添加undo,unexcute等方法,命令需要有接收者,具体行为由接收者提供,调用者仅需要知道这个命令即可

宏命令

宏命令是一组命令的集合,通过执行宏命令的方式,执行一批命令,核心思想跟消息队列是一样的,也可以是观察者模式中注册了针对一个事件注册多个个函数一样

现在我们将refresh、delete、add方法一次性全部执行一次

var macioCommand = (function () {
var commandPool = [];
return {
add(command) {
if (commandPool.includes(command)) throw new error('已存在');
else commandPool.push(command);
},
excute() {
for (var command of commandPool) {
command.excute();
}
}
}
})();
macioCommand.add(refreshCommand);
macioCommand.add(addCommand);
macioCommand.add(delCommand);
macioCommand.excute();

中介者模式

如果一个场景有好多对象,每个对象之前彼此有联系,我们将采用中介者模式

假设现在有三种动物,我们看谁吃的多

传统方式

var Cat = function () {
this.eatNumber = 0
}
Cat.prototype.eat = function (num, dog, pig) {
this.eatNumber = num;
var arr = [this.eatNumber, dog.eatNumber, pig.eatNumber];
arr.sort(function (pre, next) {
return next - pre;
})
console.log('cat当前排名:' + arr.indexOf(this.eatNumber) + 1);
} var Dog = function (cat, pig) {
this.eatNumber = 0
}
Dog.prototype.eat = function (num, cat, pig) {
this.eatNumber = num;
var arr = [this.eatNumber, cat.eatNumber, pig.eatNumber];
arr.sort(function (pre, next) {
return next - pre;
})
console.log('dog当前排名:' + arr.indexOf(this.eatNumber) + 1);
}
var Pig = function () {
this.eatNumber = 0
}
Pig.prototype.eat = function (num, dog, cat) {
this.eatNumber = num;
var arr = [this.eatNumber, dog.eatNumber, cat.eatNumber];
arr.sort(function (pre, next) {
return next - pre;
})
console.log('pig当前排名:' + arr.indexOf(this.eatNumber) + 1);
} var cat = new Cat();
var dog = new Dog();
var pig = new Pig();
cat.eat(20, dog, pig);
dog.eat(50, cat, pig);
pig.eat(100, cat, dog);

传统模式的实现方式,在执行eat的时候我们需要将另外两种动物传进去做比较,那么如果我们将比较的方式抽出来实现

var Cat = function () {
this.eatNumber = 0
}
Cat.prototype.eat = function (num) {
this.eatNumber = num;
middle(this);
} var Dog = function (cat, pig) {
this.eatNumber = 0
}
Dog.prototype.eat = function (num, cat, pig) {
this.eatNumber = num;
middle(this);
}
var Pig = function () {
this.eatNumber = 0
} Pig.prototype.eat = function (num, dog, cat) {
this.eatNumber = num;
middle(this);
} var middle = (function () {
var pool = [];
return function (target) {
pool.push(target.eatNumber);
pool.sort(function (pre, next) {
return next - pre;
})
console.log('当前排名:' + pool.indexOf(target.eatNumber) + 1);
}
})() var cat = new Cat();
var dog = new Dog();
var pig = new Pig();
cat.eat(20, dog, pig);
dog.eat(50, cat, pig);
pig.eat(100, cat, dog);

职责链模式

职责链模式在我们平时写业务逻辑是后比较常用,当一个函数处理很多东西的时候,我们通过职责链模式将其拆分

常规形式代码

var order = function (orderType, pay, stack) {
if (orderType === 1) {
if (pay == true) {
console.log('500元定金')
} else {
if (stack > 0)
console.log('普通购买')
else
console.log('库存不足')
}
} else if (orderType === 2) {
if (pay == true) {
console.log('200元定金')
} else {
if (stack > 0)
console.log('普通购买')
else
console.log('库存不足')
}
} else {
if (stack > 0)
console.log('普通购买')
else
console.log('库存不足')
}
}

我们通过职责链模式进行改进

var order500 = function (orderType, pay, stack) {
if (orderType === 1 && pay === true)
console.log('500定金');
else
order200(orderType, pay, stack);
} var order200 = function (orderType, pay, stack) {
if (orderType === 2 && pay === true)
console.log('200定金');
else
order(orderType, pay, stack);
} var order = function (orderType, pay, stack) {
if (stack > 0)
console.log('普通购买')
else
console.log('没有库存')
}

设想一下,我们平时是不是经常封装一个请求呢,那么我们对这个请求利用职责链模式进行修改让请求变成三部分组成,请求前,获取请求,请求后呢

方法模板模式

方法模板模式是一种只需要对只需要继承就可以实现的非常简单的设计模式

方法模板模式有两部分组成,一部分是抽象父类,第二部分是具体实现子类

抽象父类封装字类算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺序,字类通过继承的方式继承这个抽象类,并可以重写父类方法

就用一个很有名的例子咖啡有茶来实现吧

先泡一杯茶

function Coffee() {

}

Coffee.prototype.boilWater = function () {
console.log('把水煮沸')
} Coffee.prototype.brewCoffee = function () {
console.log('冲咖啡')
} Coffee.prototype.init = function () {
this.boilWater();
this.brewCoffee();
} var coffee = new Coffee();
coffee.init();

再泡一杯咖啡吧

function Tea() {

}

Tea.prototype.boilWater = function () {
console.log('把水煮沸')
} Tea.prototype.steepTea = function () {
console.log('冲茶水')
} Tea.prototype.init = function () {
this.boilWater();
this.steepTea();
} var tea = new Tea();
tea.init();

这个过程大同小异,只是材料跟步骤变了,我们如何改善呢

//方法与模板模式
var Beverage = function () { } //相同的方法
Beverage.prototype.boilWater = function () {
console.log('烧水')
} //冲茶或者冲咖啡 不同方法
Beverage.prototype.brew = function () { } Beverage.prototype.init = function () {
this.boilWater();
this.brew();
} //创建Tea字类 function Tea() { }
//继承模板类
Tea.prototype = new Beverage();
//重写brew满足茶的过程
Tea.prototype.brew = function () {
console.log('冲茶水')
} var tea = new Tea();
tea.init(); //创建Coffee function Coffee() { } //继承模板类
Coffee.prototype = new Beverage();
//重写brew满足茶的过程
Coffee.prototype.brew = function () {
console.log('冲咖啡')
} var coffee = new Coffee();
coffee.init();

那么什么是模板方法模式的核心是什么,就是这个init,这种设计模式我们在自己封装控件的时候会经常用到,

封装控件一定会有什么,initProps初始化属性,initEvent方法绑定,render渲染等等,我们是不是可以采用这种设计模式去做呢~

好了。以上就是js常用的16种设计模式,有些是看书理解的,有的是自己理解,可能有误差,希望指正,感谢感谢。

代码地址:https://github.com/Dqhan/DesignPattern,求星星,么么哒

Javascript十六种常用设计模式的更多相关文章

  1. 常用的Java工具类——十六种

    常用的Java工具类——十六种 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选 ...

  2. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

  3. Javascript中最常用的55个经典技巧

    Javascript中最常用的55个经典技巧1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键<table ...

  4. java常用设计模式总览

    一.java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组 ...

  5. JavaScript中的常用的数组操作方法

    JavaScript中的常用的数组操作方法 一.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,仅会返回被连接数组的一个副本. var arr1 = [1,2 ...

  6. Android常用设计模式(二)

    Android常用设计模式之观察者模式 观察者设计模式在Android应用中会经常用到,模式原理类似于这样的场景: 用户订报纸,然后在报社登记,报社来统计用户(添加用户),用户也可以取消订阅,报社删除 ...

  7. 代码重构 & 常用设计模式

    代码重构 重构目的 相同的代码最好只出现一次 主次方法 主方法 只包含实现完整逻辑的子方法 思维清楚,便于阅读 次方法 实现具体逻辑功能 测试通过后,后续几乎不用维护 重构的步骤 1  新建一个方法 ...

  8. IOS开发常用设计模式

    IOS开发常用设计模式 说起设计模式,感觉自己把握不了笔头,所以单拿出iOS开发中的几种常用设计模式谈一下. 单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们 ...

  9. SEO站长必备的十大常用搜索引擎高级指令

    作为一个seo人员,不懂得必要的搜索引擎高级指令,不是一个合格的seo.网站优化技术配合一些搜索引擎高级指令将使得优化工作变得简单.今日就和大家聊聊SEO站长必备的十大常用搜索引擎高级指令的那些事儿. ...

随机推荐

  1. MyBatis基本使用步骤

    MyBatis是一个数据持久层(ORM)框架.把实体 类和SQL语句之间建立了映射关系,是一种半自 动化的ORM实现.MyBATIS需要开发人员自己来写sql语句,这可以增加了程序的灵活性,在一定程度 ...

  2. (三)mybatis级联的实现

    mybatis级联的实现 开篇         级联有三种对应关系: 1.一对一(association):如学号与学生  2.一对多(collection):如角色与用户  3.多对多(discri ...

  3. 创业的游戏 明星APP上市前后的冰火两重天

    明星APP上市前后的冰火两重天" title="创业的游戏 明星APP上市前后的冰火两重天"> 当下,似乎只有创业才是能够实现笑看风云变幻的那条"黄金通道 ...

  4. MySQL5.7彻底取消主从复制

    由于手误在master节点执行了stop slave;->change master to XXX;->start slave;的动作,后面虽然使用stop slave停止了主从复制,但是 ...

  5. 将Hexo网站托管到Coding.net

    只需要注册coding.net,然后建立一个名为用户名+coding.me的仓库即可,需要注意的是 coding.net的pages仓库只能有一个master分支 开始使用 Coding Pages官 ...

  6. iOS 9,为前端世界都带来了些什么?「译」 - 高棋的博客

    2015 年 9 月,Apple 重磅发布了全新的 iPhone 6s/6s Plus.iPad Pro 与全新的操作系统 watchOS 2 与 tvOS 9(是的,这货居然是第 9 版),加上已经 ...

  7. IPFS初窥

    虽然区块链有很多令人兴奋的特性,但是也有其固有的缺点.比如,文件或者长度较长的文本信息就不适合存储在链上.那么如何解决这个缺点呢?一个解决方案就是IPFS(Interplanetary File Sy ...

  8. C++银行储蓄程序代码

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  9. IdentityServer4迁移至3.x版本注意问题详解

    前言 之前有一位购买我课程的童鞋利用最新的IdentityServer4版本即对应.NET Core 3.x,发布到生产环境在学习,结果出了一些问题,此前我并未过多关注IdentityServer4升 ...

  10. sql--测试商品的重要度,是否需要及时补货

    表1:商品表 表2:商品售卖表 需求:算出商品的平均点击率.平均销售.商品受欢迎度 1.使用inner join查出每件商品的点击率和销售额度 ) as selas from test a left ...