从线条小狗纯真的爱情中窥见面向对象、面向接口编程与代理模式

326 阅读9分钟

前言

在编程的世界里,面向对象编程(OOP)是一种强大的设计思想,而面向接口编程和代理模式则是 OOP 中的高级技巧。今天,我们通过一个有趣的故事——“小狗送花”,来深入理解这两种设计思想。

故事背景

我们今天要讲的故事,和两只可爱的小狗有关~

小白.png 小鸡毛.png

呐呐,就是它们啦~~

左边的是故事的女主角——小白,她是一只能量满满、爱吃小蛋糕的马尔济斯犬;右边的是男主——小鸡毛,他是一只不太聪明但脑子里面装满了小白的金毛。或许你也认识它们,它们就是韩国插画师moonlabstudio笔下的线条小狗,当然,不认识也不要紧,因为它们也不想当大明星,只需要一直可爱就好噜~

这里呢,我们可以建立两个对象,用来表示小鸡毛和小白

const Maltese = {   //这是小白 
  name: '小白',   // 名字,key value,字符串
  age: 3,   // 年龄,数值类型
  hometown: '马其他岛',   //家乡,字符串
  isSingle: true   //是否单身?布尔类型(boolean)
}
const GoldenRetriever = {   //这是小鸡毛
  name: '小鸡毛',   //名字
  age: 3,   //年龄
  hometown: '小狗镇',   //家乡
  isSingle: true   //是否单身?
}

小鸡毛可太喜欢小白了,所以,它一直都想约小白一起出去吃狗狗堡。那么,它要怎么把小白约出来嘞?这使得小鸡毛那颗小小的脑袋里面出现了大大的疑惑,当然,脑袋里除了疑惑,剩下的部分全是小白!突然,它想到了一个好办法,那就是送花给小白。它找来了很多很多的小花,兴高采烈地去找小白。可是,它发现小白正在生闷气呐,心情很不好,心情值只有30!

这里,我们可以把“心情值”这个属性加到小白身上:

xq = 30,   //心情值

然后,小鸡毛要送花,对吧?所以我们可以为小鸡毛添加这一行为

sendFlower: function (girl) {
    console.log(GoldenRetriever.name + '给' + girl.name + '送了99朵玫瑰')
    girl.receiveFlower(GoldenRetriever)
}

这个函数由小鸡毛来调用,而形参在实际调用时可以换成送花的对象的名字(也就是说,小鸡毛可以给任何人送花)

可是,只有小鸡毛单方面送花显然是不行的,所以,小白也要会收花,接下这份来自笨笨鸡毛的爱!

但是,要让小白大王接受小鸡毛的爱意也是有条件的,小白心情不好的时候,可别想让它收下小花!

所以,我们可以给小白这一对象添加如下函数

receiveFlower: function (sender) {
    console.log(Maltese.name + '收到了' + sender.name + '送的99朵玫瑰')
    if (Maltese.xq > 90) {
      console.log('我们粗去丸叭~')
    } else {
      console.log('no ~~~')
    }
  }

小白的心情值大于90的时候,才会收下小鸡毛的花并和它一起出去吃狗狗堡,否则,它就会对鸡毛say no。

好啦,回到两只小狗的故事。小鸡毛看小白心情不好,觉得自己现在送花给小白肯定没戏。怎么办呢?这可让小鸡毛犯了难。碰巧这时奥咕走过↓↓↓

奥咕.png

小鸡毛知道,奥咕是小白的好朋友,于是,它灵机一动,想让奥咕帮自己送花给小白,毕竟它可是小白的好朋友呢,肯定有办法让小白高兴起来然后收下它的花。其实,奥咕和小鸡毛也有点关系——但不是很亲密的关系,只是同乡。哎呀,老乡见老乡,两眼泪汪汪。小鸡毛,你这个忙,我奥咕肯定会帮!

好,再停一下,这里是不是又来了一个小伙伴?那我们要做什么?欸嘿,当然是跟之前一样,创建一个对象啦~

const Ogu = {
  name: '奥咕',
  age: 3,
  hometown: '小狗镇',    //老乡
}

它要收下小鸡毛的花,然后送给小白,所以,它需要会收花和送花,当然,它如果想要成功把花送给小白的话,还要会一点点魔法,让小白心情变好。所以,我们需要向它添加一个函数,先收花,再送花。(送花给小白也就是让小白收花,这里很关键哦,想想看,怎么实现?)

receiveFlower: function (sender) {
    // if (sender.name === '小鸡毛') {
    //   console.log('小鸡毛,让我们在一起吧');
    //   return 
    // }  请原谅我开的这一个小小的玩笑哈(手动狗头)小鸡毛是不会跟其它人在一起的,它心里只有小白!这里没有NTR!!!
    setTimeout(() => { // 定时器
      Maltese.xq = 99;   //奥咕用了点小魔法,小白瞬间开心了起来,心情值涨到了99!
      Maltese.receiveFlower(sender)   //把花送给小白
    }, 3000)   //3秒后再送

哦~原来,我们还可以调用之前的那个添加给小白的receiveFlower函数啊。让小白这个对象调用这个收花函数,不就实现了让小白收花吗?

最后,我们再让小鸡毛把花送给奥咕:

GoldenRetriever.sendFlower(Ogu)

来吧,让我们看看运行结果!

image.png

3秒后,

image.png

就这样,小鸡毛成功地通过奥咕把花送到了小白手上,然后高高兴兴地出去玩耍啦~

逻辑复盘

首先,小白心情不好,这是前提;小鸡毛发现小白心情不好,知道直接送花肯定没戏,所以让小白的好朋友奥咕替自己把花送给小白。其中,小鸡毛会送花,奥咕作为中间人既要会收花又要会送花,而小白要会收花,也就是:

小鸡毛送花---→奥咕收花---→奥咕让小白心情变好---→奥咕送花---→小白收花

这其中有两次发送和接收,不知道‘发送’和‘接收’这组概念能否让你联想到U盘插入电脑传输数据呢?

这其中的交互靠什么实现的?两个字:接口。

接口

什么是接口? 在编程中,接口(Interface)定义了一组方法签名,任何实现该接口的类都必须提供这些方法的具体实现。接口的核心思想是“约定优于实现”,即通过定义统一的接口,确保不同的类可以互换使用。

故事中的接口

在小狗送花的故事中,小白和奥咕都实现了 receiveFlower 方法。这个方法就是它们的“接口”。无论谁实现了这个方法,都可以接收花。小鸡毛并不关心花是直接送给小白,还是通过奥咕转送,只要对方实现了 receiveFlower 方法,就可以完成送花的任务。

面向接口编程的好处

  1. 灵活性 :通过接口,我们可以轻松替换不同的实现。例如,小鸡毛可以送花给小白,也可以送花给奥咕,只要它们都实现了 receiveFlower 方法。
  2. 可扩展性 :如果需要新增一个接收花的对象,只需实现 receiveFlower 方法即可,无需修改现有代码。
  3. 解耦 :小鸡毛不需要知道具体的接收者是谁,只需知道对方实现了 receiveFlower 方法。这种解耦使得代码更易于维护和扩展
  4. 可互换性 :小白和奥咕有相同的 receiveFlower() 方法,这体现了接口思想的重要性:只要对象具备相同的方法签名,就可以相互替换使用。

代理模式思想

什么是代理模式? 代理模式(Proxy Pattern)是一种结构型设计模式,它通过创建一个代理对象来控制对另一个对象的访问。代理对象通常会在访问真实对象之前或之后执行一些额外的操作。

故事中的代理模式

在故事中,奥咕就是小白的代理。小鸡毛把花送给奥咕,奥咕在收到花后,先让小白的心情值上升,再把花转送给小白。奥咕在这个过程中起到了“代理”的作用。生活中也不乏这样的例子,比如邮差送信、外卖小哥商家把外卖送到顾客手中,这些例子都体现了“代理”的思想,通俗地讲,就是“我想跟你交互,但是没办法直接跟你交互,那我就找个能既可以跟你交互,也能跟我交互的人,来实现我们之间的间接交互。”

const Ogu = {
  name: '奥咕',
  room: '408',
  hometown: '小狗镇',
  receiveFlower: function (sender) {
    setTimeout(() => {
      Maltese.xq = 99;
      Maltese.receiveFlower(sender);
    }, 3000);
  }
};

↑↑↑奥咕就是那个代理人(中间人)

代理模式的好处

  1. 控制访问:代理可以在访问真实对象之前或之后执行一些操作。例如,奥咕在转送花之前,先让小白的心情值上升;
  2. 延迟加载:代理可以延迟真实对象的创建或初始化,直到真正需要时。例如,奥咕可以在收到花后才让小白的心情值上升;
  3. 增强功能:代理可以在不修改真实对象的情况下,为其添加额外的功能。例如,奥咕可以在转送花时添加一些额外的逻辑。

面向对象

什么是面向对象

面向对象(Object Oriented)是软件开发方法,一种编程范式。

面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。 在现实世界中,每个人都有一些属性(年龄、身高等)和行为(跑步、学习等),而面向对象就是将这些属性和行为分别用一些变量/常量方法来实现对现实中对象的抽象。从而在计算机中描述这些对象,对这些对象进行操作,从而使虚拟世界中的对象更贴近现实世界中的对象,说白了就是在模拟现实世界。现实世界是怎样的,我们就怎么写,就是这么简单~

面向对象的好处

  1. 模块化:将代码划分为独立的对象,便于维护和复用。
  2. 封装性:隐藏内部细节,通过接口交互,提升安全性和易用性。
  3. 继承与多态:通过继承复用代码,多态支持灵活扩展,增强可扩展性。
  4. 最大的好处:使编程更符合人的思维,更贴合现实世界

总结

通过“小鸡毛送花”的故事,我们深入理解了面向对象编程、面向接口编程和代理模式的思想。面向对象是虚拟世界对现实世界的模拟,使程序更贴近现实;面向接口编程通过定义统一的接口,使得代码更加灵活、可扩展和解耦;而代理模式则通过创建代理对象,控制对真实对象的访问,增强了代码的功能和灵活性。