一些程序设计模式的整理

一些个人的整理,仅仅是一些简单的描述,如需深入了解请查找相关资料。

举了一些现实生活中的例子来方便理解,仅供参考,如有错误欢迎指出!

设计模式

原型模式

所有对象都有他的原型,当需要创建该对象时,仅需克隆原型即可实现。

举例:造一辆车子,你只需要拿到设计图,根据设计图来制造,而不是去找一辆车子然后分析它的结构来制造。

伪代码:

// 看做是设计图(原型)
class Car {
  constructor(brand) {
    this.brand = brand;
  }
}

// 可以把 new 操作符看做是制造一辆车
var myCar = new Car("BMW");

单例模式

保证一个类仅有一个实例。

举例:假设一个车站只能有一个售票处。仅仅只需要这个售票处就能卖车票,而不是卖一张票就设立一个售票处。

伪代码:

class TicketOffice {
  buyTicket() {
    return "一张车票";
  }
}

var ticketOffice = null;

function getTicketOffice() {
  // 保证只有一个 TicketOffice 实例。
  if (ticketOffice === null) {
    ticketOffice = new TicketOffice();
  }
  return ticketOffice;
}

var ticket = getTicketOffice().buyTicket();

策略模式

实现一个功能可以有不同的方法。

举例:从长沙到兰州,可以选择坐火车、坐飞机,也可以选择骑扫帚()。

伪代码:

// 不同交通方式
var transportations = {
  train: () => {
    console.log("坐火车");
  },
  airplane: () => {
    console.log("坐飞机");
  },
  broom: () => {
    console.log("骑扫帚");
  }
}

// 去兰州
function goToLanZhou(way) {
  transportations[way]();
}

// 骑扫帚去
goToLanZhou("broom");

代理模式

发生某个行为,必须先经过“审查”。审查中可以修改结果。

举例:进入高铁站,你需要先出示健康码。如果为红色则不放行。

伪代码:

function enterRailwayStation(person) {
  console.log(person.name + " 进入了高铁站")
}

function proxyEnterRailwayStation(person) {
  // 检查健康码
  if (person.healthCode === "Red") {
    throw Error("健康码为红色,禁止通行")
  }
  // 放行
  enterRailwayStation(person)
}

var person = {
  name: "田所浩二",
  healthCode: "Red"
}

proxyEnterRailwayStation(person)

迭代器模式

这个已经非常常见了吧,就是平常我们说的循环遍历。

举例:从装满书的书包里把书一本一本取出来。

伪代码:

var bag = [
  "《语文书》",
  "《数学书》",
  "《魔导书》"
]

for (var book of bag) {
  console.log(book)
}

发布-订阅模式

事件发送者发布事件,事件订阅者接收事件。

举例:你订阅了《魔女之旅》。当该番剧更新时你将会收到更新通知。

伪代码:

// 订阅番剧更新消息
majonotabitabi.addEventListener("update", function(episode) {
  console.log("《魔女之旅》第 " + episode + "话更新啦!")
})

// 发布番剧更新消息
majonotabitabi.dispatch("update", "1")

命令模式

字面意,就是发出命令,然后执行。

举例:给爷学狗叫三声啊三声

伪代码:

var you = {
  bark() {
    console.log("汪!")
  }
}

you.bark()
you.bark()
you.bark()

组合模式

可以看做是组合了多个命令,然后一键执行。也就是 部分-整体 的结构。

举例:你只需要去肯德基大喊一声“异世相遇,尽享美味”。店员就会给你下单,然后制作汉堡、可乐等食物。你无须关心之后发生了什么(你只需要承受社会性死亡的后果2333)

伪代码:

function createOrder() {
  console.log("创建订单")
}

function makeFood() {
  console.log("制作食物")
}

function socialDeath() {
  console.log("社会性死亡")
}

// 下单
function order() {
  console.log("异世相遇,尽享美味")
  createOrder()
  makeFood()
  socialDeath()
}

// 你只需要调用这一个方法即可
order()

模板方法模式

把一段代码的抽象部分提取出来,提高可复用性。

举例:填表,你不需要每次填表都要画表格,你只需要提前制作一份模板,需要的时候直接用就行了。

伪代码:

function makeSentence(obj) {
  return "请问您今天要来点" + obj + "吗?"
}

console.log(makeSentence("兔子"))

享元模式

如共享某一对象,需要的时候修改属性即可,节省内存。

举例:一千件衣服不需要去找一千个模特试穿,只需要找一个,换上不同的衣服即可。

伪代码:

class Model {
  constructor() {
    this.wearing = ""
  }
  takePhoto() {
    console.log("拍照:" + this.wearing)
  }
}

var clothes = [
  "女仆装",
  "魔女装"
]

var model = new Model()

for (var cloth of clothes) {
  model.wearing = cloth;
  model.takePhoto()
}

职责链模式

不同职责交给不同方法去完成,一般配合单一职责原则使用。

举例:寄快递,你只需要把东西交给快递员,快递员会负责打包和打印运单,到快递站后将会交给送货司机运输到下一站,以此类推。

伪代码:

function sendPacket(packet) {
  console.log("你发送了一个包裹" + packet)
  makePacket(packet)
}
function makePacket(packet) {
  console.log("打包 " + packet)
  printOrder(packet)
}

function printOrder(packet) {
  console.log("打印订单 " + packet)
  // 省略
}

sendPacket("《JS从入门到放弃 》")

中介者模式

在执行一些操作前,执行另外一些操作(比如判断参数是否合法等)

举例:网购一件商品时得先确认有没有库存。

伪代码:

var stock = {
  "昏睡红茶": 114514,
  "清醒绿茶": 0
}

function isInStock(item) {
  return stock[item] > 0
}

function purchase(item) {
  // 查询是否还有货
  if (!isInStock(item)) {
    console.log(item + " 卖光了")
    return
  }
  console.log("买到了 " + item)
}

purchase("昏睡红茶") // 买到了
purchase("清醒绿茶") // 卖光了

装饰者模式

“装饰”方法。如在某方法执行之前,执行日志记录,这也是最常见的一种用法。正如字面意,少了这个装饰基本不会影响原有方法的运行。

举例:每做完一件事,就在 Todo List 上打钩。

伪代码:

function _doHomework() {
  console.log("写作业")
}

function doHomework() {
  _doHomework();
  console.log("作业写完了,可以在 Todo List 上打钩了")
}

doHomework()

状态模式

方法内有内部状态。

举例:电灯有开关两种状态。

伪代码:

function makeBulb() {
  var state = "off"
  return {
    switch() {
      if (state === "off") {
        console.log("打开电灯")
        state = "on"
      } else {
        console.log("关闭电灯")
        state = "off"
      }
    }
  }
}

var bulb = makeBulb()

bulb.switch() // 打开电灯
bulb.switch() // 关闭电灯

适配器模式

如用新方法对输入参数进行处理,以适应旧方法。

举例:电源适配器就是一个例子。通常上面会标上额定电压 110V~220V 以适配不同标准的电源。

function charge220V(device) {
  if (device.maxVoltage < 220) {
    console.log("Boom!!!")
  } else {
    console.log("充电中")
  }
}

function adapter(device) {
  // 这里省略一些代码,毕竟是伪代码
  return {
    maxVoltage: 220
  }
}

var device = {
  maxVoltage: 110
}

charge220V(device) // Boom!
charge220V(adapter(device)) // 充电中

设计原则

单一职责原则

每个方法有且只有一个职责。

举例:快递员只负责揽件,打印运单交给业务员,运送包裹交给司机。快递员不能把这些工作全承包了。

最少知识原则

软件实体尽可能少与其他实体发生相互作用。

举例:举办一个大型活动,作为活动举办者不应该去逐个通知,而应该发布公告,参与者应该订阅这个公告事件(这是其中一个例子,还有其他例子不一一列举)。

开放-封闭原则

软件实体(类、模块、函数)等应该是可以扩展的,但是不可修改。——《JavaScript 设计模式与开发实践》P263。

举例:一个很知名的例子,两家公司为了解决生生产线生产出空肥皂盒的问题,一家公司花费五百万改造生产线(改造内部),另一家公司则放了个电风扇在旁边吹走空盒子(增加新方法)。

不过个人认为后者在实际情况中只是一种妥协,各有利弊。

参考资料:《JavaScript 设计模式与开发实践》,人民邮电出版社。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值