设计模式
设计模式的概念 :
代码书写经验,为了应对各种场景,经过前人不断的总结,压缩,形成的一套又一套的代码的书写规范,形成了设计模式。针对特定问题,提出见解而有效的处理方案
比如:假设有一个空房间,我们要日复一日地往里 面放一些东西。最简单的办法当然是把这些东西 直接扔进去,但是时间久了,就会发现很难从这 个房子里找到自己想要的东西,要调整某几样东 西的位置也不容易。所以在房间里做一些柜子也 许是个更好的选择,虽然柜子会增加我们的成 本,但它可以在维护阶段为我们带来好处。使用 这些柜子存放东西的规则,或许就是一种模式
设计模式的原则 :
设计模式的原则是“找出 程序中变化的地方,并将变化封装起来”,它的关键是意图,而不是结构。
单例模式:
定义:一个类只返回一个实例,一旦创建再次调用就直接返回
如何让一个类只有一个实例,并且能够多次访问
方案一 : 修改系统默认使用
function Fn(){
// 将来给Fn身上添加一个属性,这个属性为对象,但是又不能每次都添加
// 只有第一次添加,之后都不再添加
// 判断,如果是第一次,意味着之前没有添加过,默认是undefined(转成布尔是false),如果不是第一次,意味着添加过,那么就是对象,直接跳过,执行下面的语句
if(!Fn.obj){
Fn.obj = {};
}
Fn.obj.sayHello = "hello";
return Fn.obj;
}
var f1 = new Fn();
var f2 = new Fn();
console.log(f1);
console.log(f2);
console.log(f1 === f2); //t
方案二: 利用封装实现
// 需要一个构造函数
function Person(){}
// 封装一个单例模式的调用方式
var f = (function(){
var instance; //等同于第一个写法中的Fn.obj
return function(){
// 如果没有instance这个实例对象,就创建一个,如果有了则不再创建,直接跳过,执行下一条语句return
if(!instance){
// 将构造函数赋于instance这个对象
instance = new Person();
}
return instance;
}
})(); //匿名函数直接自动执行了,得到第一个return后的函数赋于f
var p1 = f();
var p2 = f(); //f执行后得到第二个return后的instance
console.log(p1);
console.log(p2);
console.log(p1 === p2); //t
组合模式:
定义: 把几个构造函数的入口函数组合在一起,然后使用一个’遥控器’进行统一调用
简单的组合模式实现:
// 先准备一些需要批量执行的功能
class GoHome{
init(){
console.log("到家了,开门");
}
}
class OpenComputer{
init(){
console.log("开电脑");
}
}
class OpenMusic{
init(){
console.log("开音乐");
}
}
// 组合器,用来组合功能
class Comb{
constructor(){
// 准备容器,用来放置将来组合起来的功能
this.skills = [];
}
// 用来组合的功能,接收要组合的对象
add(task){
// 向容器中填入,将来准备批量使用的对象
this.skill.push(task);
}
// 用来批量执行的功能
action(){
// 拿到容器中的对象,才能批量执行
// forEach遍历容器中的对象,只需要拿到数据,所以这里只需要第一个参数,当参数只有一个时,箭头函数的小阔号可以省略
this.skills.forEach(val = >{
var.init();
});
}
}
// 创建一个组合器
var c = new Comb();
// 提前将,将来要批量操作的对象,组合起来
c.add(new GoHome());
c.add(new OpenComputer());
c.add(new OpenMusic());
// 执行组合器的启动功能
c.action();
// 在内部会自动执行所有已经组合起来的对象的功能
观察者模式:
观察者模式也叫发布订阅者模式
定义: 以观察的角度,发现对应的状况处理问题
比如在上学的时候班主任,或者是学校的教导主任等,经常喜欢在暗地里观察学生的状态,不同的状态,不同的人可能会给出不同的处理,但这不同的处理又可以同时存在
function Stu(n){
this.name = n;
this.type = function(){
if(Math.random()>0.5){
return "学习";
}else{
return "睡觉";
}
}
}
function Teac(n){
this.name = n;
this.listen = function(t,sn){
if(t == "学习"){
console.log(`${t},${sn}是好学生`);
}else{
console.log(`${t},给${sn}一个大过`);
}
}
}
function Teac2(n){
this.name = n;
this.listen = function(t,sn){
if(t == "学习"){
console.log(`嗯嗯.....`);
}else{
console.log(`给${sn}一个警告`);
}
}
}
var s = new Stu("张三");
var t = s.type();
var t1 = new Teac("班主任");
t1.listen(t,s.name);
var t2 = new Teac2("教导主任");
t2.listen(t,s.name);
策略模式:
定义: 给出多个计划,当将来发生某种状态,执行对应的计划
类似于: 选择语句的执行
如:promise中的then和catch状态,根据这两种不同的状态做出不同的操作
var p = new Promise(function(a,b){
// 异步的程序要放在这里(正在执行)
setTimeout(()=>{
// a就是在then中的第一个回调函数,表示成功要做的事情
// console.log(1);
a();
},Math.random()*1000);
setTimeout(()=>{
// b就是在catch中的第一个回调函数,表示失败要做的事情
// console.log(2);
b();
},Math.random()*1000);
});
var p2 = p.then(function(){
// 成功的预置函数
console.log("成功");
// 假设这里又返回了一个promise对象(p1),那么可以连缀执行
return p1;
// 那么在当前then的执行身上就可以拿到promise对象p1(用p2来保存p1)
});
// p1执行成功之后要做的时
p2.then(function(){
})
// promise将原来异步中的回调函数的嵌套变成连缀执行,用这种方式解决回调地狱的写法
p.catch(function(){
// 失败的预置函数
console.log("失败");
});
MVC模式:
定义: MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。
使用的MVC的目的: 在于将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。
// MVC模式:
// M:model数据
// V:view视图
// C:ctrl控制器
// 创建模型,管理多个数据
class Model{
model1(){
return "hello";
}
model2(){
return "beautiful";
}
model3(){
return "world";
}
}
// 创建视图,管理多种渲染方式
class View{
view1(data){
console.log(data);
}
view2(data){
document.write(data);
}
view3(data){
alert(data);
}
}
// 创建控制器,设定对应的指令
class Ctrl{
constructor(){
// 初始化模型和视图
this.m = new Model();
this.v = new View();
}
// 在指令中,可以读取对应的数据,放到对应的视图中
ctrl1(){
var data = this.m.model1();
this.v.view1(data);
}
ctrl2(){
var data = this.m.model3();
this.v.view2(data);
}
}
var c = new Ctrl();
c.ctrl1();
c.ctrl2();
装饰者模式:
定义: 以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。是一种“即用即付”的方式,能够在不改变对 象自身的基础上,在程序运行期间给对象动态地 添加职责
function Person() {}
Person.prototype.skill = function() {
console.log('数学');
};
// 装饰器,还会音乐
function MusicDecorator(person) {
this.person = person;
}
MusicDecorator.prototype.skill = function() {
this.person.skill();
console.log('音乐');
};
// 装饰器,还会跑步
function RunDecorator(person) {
this.person = person;
}
RunDecorator.prototype.skill = function() {
this.person.skill();
console.log('跑步');
};
var person = new Person();
// 装饰一下
var person1 = new MusicDecorator(person);
var person2 = new RunDecorator(person1);
person.skill(); // 数学
person1.skill(); // 数学 音乐
person2.skill(); // 数学 音乐 跑步
总结: 所有的设计模式的共同目标都是:高内聚,低耦合