//产生三毛这个士兵
Soldier sanMao = new Soldier();
sanMao.killEnemy(new Rifle());
}
}
有人,有,也有场景,运行结果如下所示。
士兵开始杀人...
射击...
在这个程序中,我们给三毛这个士兵一把,然后就开始杀敌了,如果三毛要使用当然也可以,直接把sanMao.killEnemy(newRifle())修改为 sanMao.killEnemy(newMachineGun())就可以了,在编写程序时Solider士兵类根本就不用知道是哪个型号的(子类)被传入。
注意 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。
我们再来想一想,如果我们有一个玩具,该如何定义呢?我们先在类图2-1上增加一个类ToyGun,然后继承于AbstractGun类,修改后的类图如图2-2所示。
图2-2 类图
首先我们想,玩具是不能用来射击的,杀不死人的,这个不应该写在shoot方法中。新增加的ToyGun的源代码如代码清单2-5所示。
代码清单2-5 玩具源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public class ToyGun extends AbstractGun {
//玩具是不能射击的,但是编译器又要求实现这个方法,怎么办?虚构一个呗!
@Override
public void shoot() {
//玩具不能射击,这个方法就不实现了
}
}
由于引入了新的子类,场景类中也使用了该类,Client稍作修改,源代码如代码清单2-6所示。
代码清单2-6 玩具源代码
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {
public static void main(String[] args) {
//产生三毛这个士兵
Soldier sanMao = new Soldier();
sanMao.killEnemy(new ToyGun());
}
}
修改了黑体部分,把玩具传递给三毛用来杀敌,代码运行结果如下所示:
士兵开始杀人...
坏了,士兵拿着玩具来杀人,射不出呀!如果在CS游戏中有这种事情发生,那你就等着被人爆头吧,然后看着自己凄凉的倒地。在这种情况下,我们发现业务调用类已经出现了问题,正常的业务逻辑已经不能运行,那怎么办?好办,有两种解决办法:
Numberone:在Soldier类中增加instanceof的判断,如果是玩具,就不用来杀敌人。这个方法可以解决问题,但是你要知道,在程序中,每增加一个类,所有与这个父类有关系的类都必须修改,你觉得可行吗?如果你的产品出现了这个问题,因为修正了这样一个Bug,就要求所有与这个父类有关系的类都增加一个判断,客户非跳起来跟你干架不可!你还想要你的客户忠诚你吗?显然,这个方案被否定了。
Numbertwo:ToyGun脱离继承,建立一个独立的父类,为了做到代码可以复用,可以与AbastractGun建立关联委托关系,如图2-3所示。
图2-3 玩具与真实分离的类图
例如,可以在AbstractToy中声明声音、形状都委托给AbstractGun处理,嘛,形状和声音都要和真实的一样了,然后两个基类下的子类自由延展,互不影响。
在Java的基础知识中,每位老师都会讲继承,Java的三大特征嘛,继承、封装、多态。继承就是告诉你拥有父类的方法和属性,然后你就可以重写父类的方法。按照继承原则,我们上面的玩具继承AbstractGun是绝对没有问题的,玩具也是嘛,但是在具体应用场景中就要考虑下面这个问题了:子类是否能够完整地实现父类的业务,否则就会出现像上面的拿杀敌人时却发现是把玩具的笑话。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-21726-2.html
给中国造成安全威胁的情势下
造了几个合格品去送检
不会是竞争对手