浅谈几种设计模式

本文详细介绍了设计模式中的元素创建型、结构型和行为型模式,包括工厂模式、建造者模式、单例模式、适配器模式、装饰器模式、代理模式、命令模式、模板模式、观察者模式和职责链模式。这些模式在软件开发中用于规范创建方式、优化结构实现和划分责任与算法。通过实例解析,帮助理解各种模式的应用场景和实际用途。
摘要由CSDN通过智能技术生成

概括

本文会说一下几个阶段中的几种设计模式,分别是元素创建型:工厂模式、建造者模式和单例模式,结构型:适配器模式、装饰器模式和代理模式,行为型:命令模式、模板模式、观察者模式和职责链模式

元素创建型

元素创建型,顾名思义就是用来创建元素,元素创建型的设计模式目的就是规范创建方式

工厂模式

隐藏创建过程,暴露共同接口
exm: 在商店里下载游戏,同时初始化并运行,商店里有很多游戏,那么Game类进行游戏的各种操作,而Shop就相当于一个工厂,只负责调用去生产即可

class Shop {
    constructor(name) {
        return new Game(name);
    }
}

class Game {
    constructor(name) {
        this.name = name;
    }

    init() {
        console.log('inint');
    }

    run() {
        console.log('run');
    }
}

const dnf = new Shop('dnf');
// const dnf = new Game('dnf');

dnf.init();//inint
dnf.run();//run
// 创建商店时快速生产了游戏

通过工厂模式,可以实现工厂和工具的分离,工具只负责自己的内在功能,而工厂只需要负责生产即可

建造者模式

拆分简单模块、独立执行 => 注重过程与搭配
exm: 优惠套餐单元,商品 + 皮肤 进行打折售卖

class Product {
  constructor(name) {
    this.name = name;
  }
  init() {
    console.log('Product init');
  }
}

class Skin {
  constructor(name) {
    this.name = name;
  }
  init() {
    console.log('Skin init');
  }
}

class Shop {
  constructor() {
    this.package = '';
  }
  create(name) {
    this.package = new PackageBuilder(name);
  }
  getGamePackage() {
    return this.package.getPackage();
  }
}

class PackageBuilder {
  constructor(name) {
    this.game = new Product(name);
    this.skin = new Skin(name);
  }
  getPackage() {
    return this.game.init() + this.skin.init();
  }
}

const dnf = new Shop();
dnf.create('dnf');
dnf.getGamePackage();//Product init  Skin init
// 每个模块独立解耦,而建造者负责创建串联整体系统

单例模式

全局只有一个实例,不能乱掉,比如Vue-router就是单例模式做的

class PlayStation {
    constructor() {
      this.state = 'off';
    }
    play() {
      if (this.state === 'on') {
        console.log('别闹,已经在happy了');
        return;
      }
      this.state = 'on';
      console.log('开始happy');
    }
    shutdown() {
      if (this.state === 'off') {
        console.log('已经关闭');
        return;
      }
      this.state = 'off';
      console.log('已经关机,请放心');
    }
    // static instance = undefined;这里写在类里面,主要是为了可读性高一点,但个人感觉写在类外面更好,将类的东西定义起来,处理方法写在外面
  	// static getInstance() {
  	//   return function() {
  	//     if(!PlayStation.instance) {
  	//       PlayStation.instance = new PlayStation();
  	//     }
  	//     return PlayStation.instance;
  	//   }();
  	// }
  }
  
  // main.js
//   PlayStation.instance = undefined;
//   PlayStation.getInstance = (function() {
//     return function() {
//       if(!PlayStation.instance) {
//         PlayStation.instance = new PlayStation();
//       }
//       return PlayStation.instance;
//     }()
//   })
  
  const ps1 = PlayStation.getInstance();
  ps1.play();//开始happy
  
  const ps2 = PlayStation.getInstance();
  ps2.shutdown();//已经关机,请放心
//   全局只要一个实例,不能乱

总结一下:
模式场景

  1. 批量生产同类型应用来满足频繁使用同一种类型需求时 - 工厂模式
  2. 当我们需要模块化拆分一个大模块,同时使模块间独立解耦分工 - 建造者模式
  3. 全局只需要一个实例,注重统一一体化 - 单例

实际应用
Button Producer:生产不同类型的按钮 => 生产多个本质相同,利用传参区分不同属性的元素 => 工厂
全局应用 router store => 只需要一个实例 => 单例
页头组件Header: 包含了title、button、breadcum => 生产多重不同类型的元素 => 建造者

结构型

功能: 优化结构的实现方式

适配器模式 - adapter

适配独立模块,保证模块间的独立解耦且连接兼容上
exm: 买了一个港行PS,插座是国标

class HKDevice {
    getPlug() {
        return '港行双圆柱插头';
    }
}

class Target {
    constructor() {
        this.plug = new HKDevice();
    }
    getplug() {
        return this.plug.getPlug() + '港行双圆柱转换器';
    }
}

const target = new Target();
console.log(target.getplug());//港行双圆柱插头港行双圆柱转换器

装饰器模式

适配独立模块,保证模块间的独立解耦且连接兼容
exm: 设备升级

class Device {
    create() {
        console.log('PS4');
    }
}

class Phone {
    create() {
        console.log('iPhone100');
    }
}

class Decorator {
    constructor(device) {
        this.device = device;
    }
    create() {
        this.device.create();
        this.update(device);
    }
    update(device) {
        console.log(device + 'Pro');
    }
}

const device = new Device();
device.create();//PS4

const devicePro = new Decorator(device);
devicePro.create();//PS4  [object Object]Pro

代理模式

使用代理人来替代原始对象
**exm:**游戏防沉迷

class Game {
    play() {
        console.log('playing');
    }
}

class Player {
    constructor(age) {
        this.age = age;
    }
}

class GameProxy {
    constructor(player) {
        this.player = player;
    }
    play() {
        return (this.player.age < 16) ? "too young to play" : new Game().play();
    }
}

const youngPlayer = new Player(15);
const youngGame = new GameProxy(youngPlayer);

console.log(youngGame.play());//too young to play

const player = new Player(18); 
const game = new GameProxy(player);
game.play();//playing

不用在原有的结构里面去添加逻辑判断,通过代理决定是否开放入口来进行实现
总结
模式场景
中间转换参数、保持模块间独立的时候 - 适配器模式
附着于多个组件上,批量动态赋予功能的时候 - 装饰器模式
将代理对象与调用对象分离,不直接调用目标对象 - 代理模式

实际应用
1.两个模块:筛选器和表格,需要做一个联动。但筛选器的数据不能直接传入表格,需要做数据结构转换
=> 模块之间独立,需要做数据结构转换 => 适配器
2.目前有按钮、title、icon三个组件。希望开发一个模块,让三个组件同时具备相同功能 => 套一层装甲对于每个组见
有统一的能力提升,且可以动态添加功能进行拓展 => 装饰器模式
3.ul中多个li,每个li上的点击事件 => 利用冒泡做委托,事件绑定在ul上 => 代理

行为型

不同的对象之间划分责任和算法的抽象化

命令模式

请求以命令的形式包裹在对象中,并传给调用对象
**exm:**对于游戏角色的控制

//接受命令者
class Receiver {
    execute() {
        console.log('已经在爬了');
    }
}
//触发命令者
class Operator {
    constructor(command) {
        this.command = command;
    }
    run() {
        console.log('给爷爬');
        this.command.execute();
    }
}
//指令执行者
class Command {
    constructor(receiver) {
        this.receiver = receiver;
    }
    execute() {
        console.log('执行命令');
        this.receiver.execute();
    }
}

const soldier = new Receiver();
const order = new Command(soldier);
const player = new Operator(order);
player.run();//给爷爬 执行命令 已经在爬了

每个角色各司其职,通过命令串联起来

模板模式

在模板中,定义好每个方法的执行步骤。方法本身关注于自己的事情
exm: 想要成功吃个鸡,大概分几步

class Device {
    constructor(executePipeLine) {
        // executePipeLine…… 可以在里边进行编排
    }
    powerOn() {
        console.log('打开电源');
    }
    login() {
        console.log('登录账号');
    }
    clickIcon() {
        console.log('点击开始游戏');
    }
    enterGame() {
        console.log('进入战场');
    }

    play() {
        this.powerOn();
        this.login();
        this.clickIcon();
        this.enterGame();
    }
}
const player = new Device();
player.play();

在类里不光进行了拆解,还进行了编排

观察者模式

当一个属性发生状态改变时,观察者会连续引发所有的相关状态改变

class MediaCenter {
    constructor() {
      this.state = '';
      this.observers = [];
    }
    attach(observer) {
      this.observers.push(observer);
    }
    getState() {
      return this.state;
    }
    setState(state) {
      this.state = state;
      this.notifyAllobservers();
    }
    notifyAllobservers() {
      this.observers.forEach(ob => {
        ob.update();
      })
    }
  }
  
  class Observer {
    constructor(name, center) {
      this.name = name;
      this.center = center;
      this.center.attach(this);
    }
    update() {
      console.log(`${this.name} update, state: ${this.center.getState()}`);
    }
  }
  
  const center = new MediaCenter();
  const ps = new Observer('ps', center);//ps update, state: on
  const tv = new Observer('tv', center);//tv update, state: on
  
  center.setState('on');

职责链

链式调用 2. 职责独立 3. 顺序执行
exm: 成年高质量男性想要打个游戏,在家里需要过几关

class Action {
  constructor(name) {
    this.name = name;
    this.nextAction = null;
  }
  setNextAction(action) {
    this.nextAction = action;
  }
  handle() {
    console.log(`${this.name}请审批,是否可以打游戏`);
    if (this.nextAction !== null) {
      this.nextAction.handle();
    }
  }
}

const dad = new Action('爸');
const mom = new Action('妈');
const wife = new Action('夫人');

dad.setNextAction(mom);
mom.setNextAction(wife);

dad.handle();
//爸请审批,是否可以打游戏
//妈请审批,是否可以打游戏
//夫人请审批,是否可以打游戏

总结
模式场景
发出指令,中间层传递命令本身,命中包含执行对象 - 命令模式
通过模板定义执行顺序,做独立操作 - 模板模式
通过观察者,可以让被观察值统一发生变化,触发相应依赖值的统一更新 - 观察者模式
独立职责的单元通过链式执行,逐步操作流程 - 职责链

实际应用
提交表单进行表单逐行校验,链式调用validate,依次执行 => 职责亮
echart准备工作:canvas、config、init、draw(),规划顺序执行 => 模板模式
调度器在接受到一组新的数据时候,解析数据,并且根据数据类型包裹在对象中传递到下级helper,helper
再去执行相应操作 => 命令模式
输入框输入的值去判断下拉框显示与否 => 观察input设置show => 观察者模式

最后

下机!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值