在 JavaScript 的世界里,设计模式就像是一个个巧妙的解决方案,帮助我们更好地组织和管理代码。今天,我们通过一个甜甜的故事 —— 小明追求小红,转托闺蜜小芳帮忙送花,来理解面向对象中的代理模式~💑
📖 故事背景
小明暗恋小红已久,但由于害羞,不敢直接表白送花。小红的闺蜜小芳和两人都很熟,于是小明想到让小芳代替自己给小红送 99 朵玫瑰花。在这个过程中,小芳就充当了小明和小红之间的代理角色,像极了代码里那个默默传递心意的 "中间人"~🤫
🧩 面向对象与代理模式
在面向对象编程中,代理模式(Proxy Pattern)是一种结构型设计模式。代理对象作为目标对象的替代品,控制对目标对象的访问。就像故事中的小芳代理小明送花一样,代理对象可以在访问目标对象前后添加额外的逻辑,比如预处理、后处理、权限控制、缓存等~🛡️
💻 代码实现
首先,我们定义目标对象小红,她有一个接收花的方法~🌹
class XiaoHong {
  receiveFlowers(flowers) {
  console.log(\`小红收到了\${flowers}朵玫瑰花,很开心!🥰\`);
  }
}
然后是小明,他本应该直接送花给小红,但通过代理小芳来实现~🤔
class XiaoMing {
  constructor(xiaoHong) {
  this.xiaoHong = xiaoHong;
  }
  sendFlowers(flowers) {
  // 小明原本想自己送花,但通过代理小芳
  // 这里可以先不直接调用小红的接收方法,而是让代理处理
  // 暂时先记录想法
  console.log(\`小明想送\${flowers}朵花给小红💭\`);
  }
}
接下来是代理对象小芳,她持有目标对象小红的引用,并且控制小明送花的过程~💁♀️ 在送花前后,可能会有一些代理特有的操作,比如小明告诉小芳送花的数量,小芳去执行送花动作,甚至可以添加一些自己的 "审查" 逻辑,比如确认小明是否真的适合小红等(这里简化为直接代理送花)~
class XiaoFangProxy {
  constructor(xiaoHong) {
  this.xiaoHong = xiaoHong;
  }
  proxySendFlowers(flowers) {
  // 代理前的操作,比如小明和小芳沟通送花事宜
  console.log(\`小明告诉小芳:"请帮我送\${flowers}朵玫瑰花给小红"📢\`);
  // 调用目标对象小红的接收方法
  this.xiaoHong.receiveFlowers(flowers);
  // 代理后的操作,比如小芳告诉小明送花结果(这里暂不体现)
  }
}
最后,我们来模拟整个过程~🎉 小明创建小红对象,然后通过小芳代理送花:
const xiaoHong = new XiaoHong();
const xiaoFang = new XiaoFangProxy(xiaoHong);
// 小明不再直接送花,而是让小芳代理
// 这里可以理解为小明原本的送花行为被代理对象接管
xiaoFang.proxySendFlowers(99);
🌟 代理模式的优点
🔐 控制访问:可以在代理对象中添加访问控制逻辑,比如只有小明才能让小芳送花,其他人不行(可以通过添加权限判断实现)~
⚖️ 解耦:小明和小红不直接交互,降低了两者的耦合度,就像现实中通过中间人沟通,避免了直接接触的尴尬~
➕ 扩展功能:在代理过程中,可以方便地添加额外的功能,比如送花前检查花的数量是否合适,送花后记录送花历史等~📊
🚀 在 JavaScript 中的实际应用
代理模式在 JavaScript 中有很多实际应用场景~比如:
🖼️ 虚拟代理:当创建目标对象代价较高时,通过代理对象延迟创建,比如图片的懒加载,先显示占位符,通过代理在需要时加载真实图片~
💾 缓存代理:代理对象可以缓存目标对象的操作结果,避免重复计算,提高性能~
🌐 远程代理:用于访问远程对象,代理对象处理网络通信等细节,客户端只需与代理交互~
通过这个小明追小红的故事,我们形象地理解了代理模式在面向对象编程中的应用~🎯 代理模式就像一个中间助手,帮助我们更好地管理对象之间的交互,让代码更加灵活和可维护。在实际开发中,根据不同的需求选择合适的代理模式,能够让我们的代码设计更加优雅~💻✨