浅谈作用多态(主人对象宠物多态原则)「使用多态实现主人给宠物喂食」

我们先来了解一个业务背景:请设计一个系统,描述主人喂养宠物的场景,首先在这个场景当中应该有“ 宠物对象”,宠物对象应该有一个吃的行为,另外还需要一个“ 主人对象”,主人对象应该有一个喂的行为,请看代码://宠物狗public class Dog {String name;public Dog(String name){this.name = name;}//吃的行为public void eat(){System.out.println(this.name + "在啃肉骨头
");}}1.2.3.4.5.6.7.8.9.10.11.
//主人public class Master {//喂养行为public void feed(Dog dog){//主人喂养宠物,宠物就吃System.out.println("主人开始喂食儿");dog.eat();System.out.println("主人喂食儿完毕");}}1.2.3.4.5.6.7.8.9.10.public class Test {public static void main(String[] args) {//创建狗对象Dog dog = new Dog("二哈");//创建主人对象Master master = new Master();//喂养master.feed(dog);}}1.2.3.4.5.6.7.8.9.10.运行结果如下图所示:以上程序编译和运行都很正常,输出结果也是对的,那么存在什么问题吗?假设后期用户提出了新的需求,软件可能面临着功能扩展,这个扩展会很方便吗?假设现在主人家里又来了一个宠物猫,那该怎么办呢?请看代码:在以上代码的基础之上,新增了一个Cat类,来表示宠物猫,这个对于程序来说是可以接受的://宠物猫public class Cat {String name;public Cat(String name){this.name = name;}//吃的行为public void eat(){System.out.println(this.name + "在吃鱼
");}}1.2.3.4.5.6.7.8.9.10.11.
另外,除了增加一个Cat类之外,我们还需要“ 修改”Master主人类的源代码,这件事儿是我们程序员无法容忍的,因为修改之前写好的源代码就面临着重新编译、重新全方位的测试,这是一个巨大的工作,维护成本很高,也很麻烦://主人public class Master {//喂养行为public void feed(Dog dog){//主人喂养宠物,宠物就吃System.out.println("主人开始喂食儿");dog.eat();System.out.println("主人喂食儿完毕");}//喂养行为public void feed(Cat cat){//主人喂养宠物,宠物就吃System.out.println("主人开始喂食儿");cat.eat();System.out.println("主人喂食儿完毕");}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.public class Test {public static void main(String[] args) {//创建狗对象Dog dog = new Dog("二哈");//创建主人对象Master master = new Master();//喂养master.feed(dog);//创建猫对象Cat cat = new Cat("汤姆");//喂养master.feed(cat);}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.运行结果如下图所示:在软件开发过程中,有这样的一个开发原则:开闭原则
开闭原则(OCP)是面向对象设计中“ 可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段
1988年,勃兰特·梅耶(Bertrand Meyer)在他的著作 《面向对象软件构造(Object Oriented Software Construction)》中提出了开闭原则,它的原文是这样:“ Software entities should be open for extension,but closed for modification”
翻译过来就是:“软件实体应当对扩展开放,对修改关闭”
这句话说得略微有点专业,我们把它讲得更通俗一点,也就是: 软件系统中包含的各种组件,例如模块(Modules)、类(Classes)以及功能(Functions)等等,应该在不修改现有代码的基础上,引入新功能
开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭”,是指对于原有代码的修改是封闭的,即修改原有的代码对外部的使用是透明的
以上程序在扩展的过程当中就违背了OCP原则,因为在扩展的过程当中修改了已经写好的Master类,怎样可以解决这个问题呢?多态可以解决,请看代码://宠物类public class Pet {String name;//吃的行为public void eat(){}}1.2.3.4.5.6.7.//宠物猫public class Cat extends Pet{public Cat(String name){this.name = name;}//吃的行为public void eat(){System.out.println(this.name + "在吃鱼
");}}1.2.3.4.5.6.7.8.9.10.
//宠物狗public class Dog extends Pet{public Dog(String name){this.name = name;}//吃的行为public void eat(){System.out.println(this.name + "在啃肉骨头
");}}1.2.3.4.5.6.7.8.9.10.
//主人public class Master {//喂养行为public void feed(Pet pet){//主人喂养宠物,宠物就吃System.out.println("主人开始喂食儿");pet.eat();System.out.println("主人喂食儿完毕");}}1.2.3.4.5.6.7.8.9.10.public class Test {public static void main(String[] args) {//创建狗对象Dog dog = new Dog("二哈");//创建主人对象Master master = new Master();//喂养master.feed(dog);//创建猫对象Cat cat = new Cat("汤姆");//喂养master.feed(cat);}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.运行结果如下图所示:在以上程序中,Master类中的方法feed(Pet pet)的参数类型定义为更加抽象的Pet类型,而不是具体Dog宠物,或者Cat宠物,显然Master类和具体的Dog、Cat类解耦合了,依赖性弱了,这就是我们通常所说的面向抽象编程,尽量不要面向具体编程,面向抽象编程会让你的代码耦合度降低,扩展能力增强,从而符合OCP的开发原则
假如说这回再来一个新的宠物猪呢,我们只需要这样做,新增加一个“宠物猪类”,然后宠物猪类Pig继承宠物类Pet,并重写eat()方法,然后修改一下测试类就行了,整个过程我们是不需要修改Master类的,只是额外增加了一个新的类:public class Pig extends Pet {public Pig(String name){this.name = name;}//吃的行为public void eat(){System.out.println(this.name + "在吃粥
");}}1.2.3.4.5.6.7.8.9.
public class Test {public static void main(String[] args) {//创建狗对象Dog dog = new Dog("二哈");//创建主人对象Master master = new Master();//喂养master.feed(dog);//创建猫对象Cat cat = new Cat("汤姆");//喂养master.feed(cat);//创建宠物猪对象Pig pig = new Pig("小猪猪");master.feed(pig);}}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.运行结果如下图所示:以上程序中到底哪里使用了多态机制呢?请看下图:通过以上内容的学习,我们可以看到多态在开发中联合方法覆盖一起使用,可以降低程序的耦合度,提高程序的扩展力
在开发中尽可能面向抽象编程,不要面向具体编程,好比电脑主板和内存条的关系一样,主板和内存条件之间有一个抽象的符合某个规范的插槽,不同品牌的内存条都可以插到主板上使用,2个G的内存条和4个G的内存条都可以插上,但最终的表现结果是不同的,2个G的内存条处理速度慢一些,4个G的快一些,这就是多态,所谓多态就是同一个行为作用到不同的对象上,最终的表现结果是不同的,主要的要求就是对象是可以进行灵活切换的,灵活切换的前提就是解耦合,解耦合依赖多态机制
浅谈作用多态(主人对象宠物多态原则)
(图片来源网络,侵删)

联系我们

在线咨询:点击这里给我发消息