设计模式 之 里氏替换原则

里氏替换原则的定义有:

如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。

定义很完备,但也不太好理解。说白了,其实就是使用到父类的地方都可以完全的替换成它的某个子类,而整个程序的运行不受任何影响。也就是说,使用父类对象调用某个成员方法,和使用其某个子类对象调用同名的成员方法,在逻辑上和结果上都需要是等价的。
这规定了,继承父类的子类,必须完完全全,不打折扣的支持父类的方法。

子类兼容父类

这条原则,是面向对象中多态的基石。在程序设计时,我们常以父类的引用来接接受某个子类的对象,再以父类的身份调用这些方法,他们可以是已经在父类中实现的,也可以是在父类中声明了原型而在子类中分别实现的。但是在调用的时候,应该看不出通过子类调用还是通过父类调用。

我们看个例子:

abstract class Animal
{
	public void die()
	{
		System.out.println("animal dead~~");
	}
	public abstract void move();
}

class Bird extends Animal
{
	public void move()
	{
		System.out.println("flying~~")}
}
class Human extends Animal
{
	public void move()
	{
		System.out.println("running~~");
	}
	public void hunt(Animal target)
	{
		target.move();
		this.move();
		target.die();
	}
}

在这个例子中,人可以猎杀一个动物,这个动物是一个父类,将它替换成某个具体的子类 Bird 或者 Human都不会对程序的运行产生任何影响。
为了实现这个要求,通常情况下,在父类方法已经实现的情况下,子类尽可能不要重写父类的方法。
当子类重载父类方法时,参数类型的设计应当将范围扩大。

父类不需要兼容子类

该原则仅规定了子类可以替换父类,而父类确实不必要可以完全兼容子类的。
子类可以在父类的基础上可以添加新的方法和成员,例如在上面的程序中,人类就多出了捕猎的方法,这时用父类对象替换子类就是不可取的,因为父类可能没有子类新增的方法。

不要忘记接口

接口可以看作一种特殊的抽象类,实现接口的类可以看作是接口的子类(尽管java的单继承仅允许存在一个父类)。
我们可以将上面的例子更改一下,抽象出一个捕食者的接口,所有实现这个接口的类都可以进行捕猎:

abstract class Animal
{
	public void die()
	{
		System.out.println("animal dead~~");
	}
	public abstract void move();
}

interface Hunter
{
	public void hunt(Animal target);
}

class Bird extends Animal
{
	public void move()
	{
		System.out.println("flying~~")}
}
class Shark extends Animal implements Hunter
{
	public void move()
	{	
		System.out.println("swimming~~");
	}
	public void hunt(Animal target)
	{
		target.move();
		this.move();
		target.die();
	}
}
class Human extends Animal implements Hunter
{
	public void move()
	{
		System.out.println("running~~");
	}
	public void hunt(Animal target)
	{
		target.move();
		this.move();
		target.die();
	}
}
...
{
	Animal a = new human();
	Hunter h = new Shark();
	Shark s = new Shark();
	h.hunt(a);
	s.hunt(a);
}

此时,作为捕食者的鲨鱼拥有捕食方法,将捕食者对象替换为它的实现类鲨鱼类对象时,这个调用在结果上仍然相同


系列文章参考资料:

  • 图解Java设计模式 。视频很全也很棒,墙裂推荐。视频就在站内。
  • 《设计模式》 设计模式的经典。
  • 《大话设计模式》非常有名的小白友好型设计模式著作。

设计模式系列文章:
面向对象 之 不能不知道的类间关系(上)泛化、实现、依赖 C++与Java
面向对象 之 不能不知道的类间关系(下)关联、聚合、组合 C++与Java
JAVA单例模式分析及其实现:饿汉式、懒汉式、双重检查、静态内部类
设计模式 之 迪米特法则
设计模式 之 设计原则(1) 单一职责原则 接口隔离原则 依赖倒转原则

你可能感兴趣的:(设计模式)