【前端设计模式】之外观模式

外观模式是一种结构型设计模式,它提供了一个简单的接口,隐藏了复杂的子系统,并使得客户端能够更方便地使用这些子系统。在前端开发中,外观模式可以帮助我们简化复杂的代码结构,提高代码的可维护性和可读性。

外观模式特性

  1. 封装复杂的子系统:外观模式通过提供一个简单的接口,将复杂的子系统封装起来。这样客户端就不需要了解子系统内部的实现细节。
  2. 简化接口:外观模式可以将多个子系统的接口进行整合和简化,提供一个更加统一和易于使用的接口给客户端。
  3. 提高代码可维护性:通过将复杂的子系统封装起来,外观模式可以减少代码之间的依赖关系,使得代码更加易于维护和修改。

应用示例

1. 挂号系统

复制代码
javascript 复制代码
// 创建外观对象
const HospitalFacade = {
  // 封装内部系统方法
  bookAppointment: function(patientName, date, time) {
    this.checkPatientName(patientName);
    this.checkDate(date);
    this.checkTime(time);
    this.makeAppointment(patientName, date, time);
  },

  // 检查患者姓名是否合法
  checkPatientName: function(patientName) {
    if (!patientName || patientName.length === 0) {
      throw new Error('请输入患者姓名');
    }
  },

  // 检查预约日期是否合法
  checkDate: function(date) {
    const currentDate = new Date();
    const selectedDate = new Date(date);

    if (isNaN(selectedDate.toString())) {
      throw new Error('请选择有效的预约日期');
    } else if (Math.abs(selectedDate - currentDate) < 86400000) {
      throw new Error('请选择至少在24小时后的预约日期');
    }
  },

  // 检查预约时间是否合法
  checkTime: function(time) {
    const selectedTime = new Date(time);

    if (isNaN(selectedTime.toString())) {
      throw new Error('请选择有效的预约时间');
    }
  },

  // 创建预约并保存到数据库中
  makeAppointment: function(patientName, date, time) {
    const appointment = {
      patientName: patientName,
      date: date,
      time: time,
    };
    // 调用数据库操作方法保存预约信息
    this.saveAppointmentToDatabase(appointment);
    console.log('预约成功!');
  },

  // 封装数据库操作方法,避免暴露底层细节给客户端调用
  saveAppointmentToDatabase: function(appointment) {
    // 在这里执行数据库操作,保存预约信息到数据库中...
  },
};

// 使用外观对象进行挂号操作
HospitalFacade.bookAppointment('张三', '2023-07-18', '14:00');

这段代码创建了一个名为HospitalFacade的外观对象,该对象封装了医院预约挂号系统的相关方法。

bookAppointment方法用于接受患者姓名、预约日期和时间作为参数,并依次进行以下操作:

  1. 调用checkPatientName方法检查患者姓名是否合法。
  2. 调用checkDate方法检查预约日期是否合法。
  3. 调用checkTime方法检查预约时间是否合法。
  4. 如果以上检查均通过,则调用makeAppointment方法创建预约并保存到数据库中。

这些方法对应于挂号系统的各个功能。客户端只需要与外观对象进行交互,而不需要直接与各个内部系统进行通信。这样可以简化客户端的代码,并隐藏内部系统的细节。同时,通过将一些复杂的逻辑封装在外观对象中,可以提高代码的可维护性和可读性。

2. 动画效果封装:

下面是一个示例代码,展示如何使用外观模式实现对动画效果的封装:

复制代码
javascript 复制代码
// 动画效果外观类
class AnimationFacade {
  constructor() {
    this.animation = new Animation();
  }

  // 外观方法:开始动画
  startAnimation() {
    this.animation.start();
  }

  // 外观方法:停止动画
  stopAnimation() {
    this.animation.stop();
  }

  // 外观方法:更新动画帧
  updateFrame() {
    this.animation.update();
  }
}

// 动画子系统类
class Animation {
  constructor() {
    this.frames = []; // 动画帧数组
    this.currentFrameIndex = 0; // 当前帧索引
  }

  // 子系统方法:开始动画
  start() {
    // 添加开始动画帧,设置初始状态等操作
    this.frames.push(new Frame('start'));
  }

  // 子系统方法:停止动画
  stop() {
    // 添加结束动画帧,设置结束状态等操作
    this.frames.push(new Frame('stop'));
  }

  // 子系统方法:更新动画帧
  update() {
    // 根据当前帧索引和帧数组更新动画状态等操作
    const frame = this.frames[this.currentFrameIndex];
    frame.update();
  }
}

// 动画帧类
class Frame {
  constructor(type) {
    this.type = type; // 帧类型,如开始、结束等
  }

  // 更新动画帧状态等操作,具体实现根据实际需求而定
  update() {
    console.log(`Frame ${this.type} updated`);
  }
}

const animation = new AnimationFacade(); // 创建动画外观对象
animation.startAnimation(); // 开始动画
animation.updateFrame(); // 更新动画帧,输出"Frame start updated"和"Frame stop updated"等日志信息,具体输出取决于`Frame`类的实现和动画效果的具体需求。
animation.stopAnimation(); // 停止动画,输出"Frame stop updated"等日志信息。

这段代码定义了一个动画效果外观类(AnimationFacade)和两个子系统类:动画子系统类(Animation)和动画帧类(Frame)。

动画效果外观类(AnimationFacade)是整个动画系统的外观,提供了一些外观方法,用于控制动画的开始、停止和更新帧。

动画子系统类(Animation)是实现动画的核心部分,它包含了动画帧数组(frames)和当前帧索引(currentFrameIndex)。该类提供了开始动画、停止动画和更新动画帧的方法。

动画帧类(Frame)表示动画中的每一帧。它只有一个类型属性(type),用于标识帧的类型。该类还提供了一个更新方法(update),用于执行具体的动画帧更新操作。

通过使用这些类,可以构建一个简单的动画系统,通过调用外观方法来控制动画的开始、停止和更新帧。具体实现可以根据实际需求进行扩展和修改。

优缺点

优点
  1. 简化接口:外观模式可以将复杂的子系统接口进行整合和简化,提供一个更加统一和易于使用的接口给客户端。
  2. 提高代码可维护性:通过将复杂的子系统封装起来,外观模式可以减少代码之间的依赖关系,使得代码更加易于维护和修改。
  3. 提高代码可读性:外观模式可以隐藏复杂的实现细节,使得代码更加易于理解和阅读。
缺点
  1. 违反开闭原则:如果需要新增或修改子系统的功能,可能需要修改外观类的代码。
  2. 可能会造成性能问题:如果外观类过于庞大,可能会导致性能下降。

总结

外观模式是一种简化复杂系统接口的设计模式,在前端开发中有着广泛的应用。它可以帮助我们封装复杂的子系统,并提供一个简单易用的接口给客户端。通过使用外观模式,我们可以提高代码的可维护性、可读性和扩展性。但是需要注意避免过度使用外观模式,以免造成不必要的性能问题。

相关推荐
百万蹄蹄向前冲6 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳58144 分钟前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter1 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
Jerry2 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉3 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog3 小时前
低端设备加载webp ANR
前端·算法
LKAI.3 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy4 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js