面向对象封装了变化,或者更加准确的说,应该是封装了不变的地方,留出了变化的地方可以在需要的时候再去变,那么什么地方会变化呢?
1、数据的变化
比如一个工厂生产一种纸盒子,程序要计算它的体积,需要有长、宽、高的尺寸,盒子的尺寸是固定的,那么在代码里面直接硬编码,比如长1,宽2,高3,方法返回1*2*3,甚至直接返回6,没有任何问题。现在需求发生了变化,这个工厂生产两种尺寸的盒子,另一种长2宽2高2,这时候变化的就是数据。使用变量来抵御数据的变化。我现在只要在计算体积的方法里设长宽高三个参数,在方法里返回长*宽*高就可以了。这里不变的是计算体积的过程、长宽高的变量,变化的是计算用到的数据。
2、过程的变化
现在厂家又生产了另一种底面是三角形的三棱柱盒子,这时候原来计算体积的公式就不好用了。这里注意了,计算体积的这个过程是要的,但是这个过程怎么实现需要变化了。使用继承和重写来抵御过程的变化。可以把计算体积的方法变成一个虚方法,然后在继承的类里面重写它,返回长*宽*高/2。这里不变的是,必然会需要计算体积的这种行为,而这个行为的过程是变化的,行为需要的数据值也是变化的。
3、参数的变化
厂家生产了第三种产品,底面积是圆形的,圆柱形的盒子。这时候需要的参数不是长宽高了,而是半径和高两个变量。这时候计算体积的方法已经不能用原来传入三个参数了。使用属性来抵御参数的变化。这时候我们在抽象的父类里面只要提供计算体积的无参数方法,然后在子类里面自定义不同的属性就可以了。比如在长方体盒子子类里定义长宽高、在圆柱形盒子子类里定义半径和高。等等。
4、行为的增加
现在又有第二家工厂来找我们做程序了,它们计算体积时除了盒子的体积后还需要在加一个包装的体积。然后第三家工厂需要在体积上乘以一个1.05的材料消耗系数。虽然它也可以用继承来抵御变化,但是它并不是纯粹的计算盒子的体积了。而且各种厂家行为古怪,无法预知会有什么样子的行为变化。用事件来抵御行为的增加。在计算盒子体积的方法里面引发一个计算盒子体积后的事件,让处理事件的人可以得知计算的参数以及计算的结果,并且可以改变它。那么在为第二、三家工厂做程序时候,就可以在计算盒子体积的事件里面处理新的行为。在这里不变的仍然是需要计算体积这种行为,变化的是在这种行为后会有很多附加的行为,而且是未知的。