设计模式 里氏替换原则

设计模式 里氏替换原则

继续里氏替换原则。

上回栗子为正方形不能被长方形继承,这次,具体

子类必须实现父类的方法

类图

对具体代码进行实践

// 定义抽象类枪
public abstract class AbstractGun{
	// 定义枪
	public abstract void shoot();
}
// 定义手枪,步枪,机枪
public class Handgun extends AbstractGun{
	// 定义手枪
	public void shoot(){
	}
}
public class Rifle extends AbstractGun{
	public void shoot(){
	}
}
public class MachineGun extends AbstractGun{
	public void shoot(){
	}
}

接着拥有枪,定义士兵

public class Soldier{
	// 让其获得具体的枪的对象
	private AbstractGun gun;
	// 给其一把枪
	public void setGun(AbstractGUn _gun){
		this.gun = _gun;
	}
	// 定义杀敌的行为
	public void killEnemy(){
		gun.shoot();	// 使用对象的shoot方法
	}
}

最后定义整个场景

public class Client{
	public static void main(String[] args){
		// 产生士兵
		Soldier sanMao = new Soldier();
		// 给其一只枪
		sanMao.setGun(new Rifle());
		// 杀敌
		sanMao.killEnemy();
	}
}

在场景中,三毛需要什么枪支,就直接new 出一个枪支即可,然后其内通过抽象类获取到对象,然后对齐进行修饰

装饰器模式

更改枪支

如果要更改枪支,直接增加新的类即可

由于玩具枪不能射击,所以代码如下

public class ToyGun extends AbstractGun {
	public void shoot(){
	}
}

对参加进行修改

public class Client{
	public static void main(String[] args){
		Soldier sanMao = new Soldier();
		sanMao.setGun(new ToyGun());
		sanMao.killEnemy();
	}
}

由于之前在士兵类中定义了shoot方法,导致三毛杀敌,业务出现问题

解决,只能再次定义一个新的玩具枪的抽象类和强的抽象类之间存在泛化关系

子类可以拥有行为和外观

对步枪继续继承一些类,该类更加详细

实现以下AUG类

public class AUG extends Rifle {
	// 对阻击枪设置一个望远镜
	public void zoomOut(){
	}
	// 重写父类的射击方法
	public void shoot(){
	}
}

需要增加阻击手和阻击枪之间存在组合关系

uml图如下

实现阻击手

public class Snipper{
	public void killEnemy(AUG _ang){
		_ang.zoomOut();	// 先查看情况
		// 射击
		ang.shoot();
	}
}

这就可以啦。在场景中可以杀死敌人

public class Client{
	public static void main(String[] args){
		Snipper sanMao = new Snipper();
		sanMao.setRiffle(new AUG);	// 给三毛一只枪
		sanMao.killEnemy();	// 进行设计
	}
}

这里直接将子类传递进入。

Java中向下转型不安全

public class Client{
	public static void main(String[] args){
		Snipper sanMao = new Snipper();
		sanMao.setRiffle(new AUG);	// 给三毛一只枪
		sanMao.killEnemy();	// 进行设计
	}
}

好吧,在子类出现的地方,父类未必就可以出现。。。向下强制转型,不安全

覆盖或实现父类的方法时输入参数可以被放大

里式替换原则要求定义一个契约,即父类或接口,即契约设计。

// 定义一个转换类
public class Father{
	public Collection doSomething(HashMap map){
		return map.values();
	}
}

这个类完成转换

然后定义子类

public class Son extends Father {
	// 将输入放大
	public Collection doSomething(Map map){
		return map.value();
	}
}

然后接着使用

public class Client{
	public static void main(String args){
		// new 出父类
		Father f = new Father();
		HashMap map = new HashMap();
		f,doSOmething(map);
	}
}

在上方中父类被执行

根据里氏替换原则,子类能替代父类

public class Client{
	public static void main(String[] args){
		SOn f = new Son();
		HashMap map = new HashMao();
		f.doSomething(map);
	}
}

上方的即为里氏替换原则。

子类代替父类传入,子类永远不会被执行。子类要运行,必须重写父类。或者是参数的范围更宽

举例子,如果父类参数条件大,子类参数条件小

public class Father{
	public Collection doSomething(Map map){
		return map.values();
	}
}
public class Son extends Father{
	public Collection doSomething(HashMap map){
		return map.values();
	}
}

接着运行

public class Client{
	public static void main(String[] args){
		Father f = new Father();
		HashMap map = new HashMap();
		f.doSomething(map);
	}
}

此时可以运行

根据里氏替换原则,子类能使用的地方,父类也能使用。

public class Client{
	public static void main(String[] args){
		Son f = new Son();
		HashMap map = new HashMap();
		f.doSomething(map);
	}
}

子类被执行,

总结

重载实现父类的时候,输入的参数要求放大

重写,实现父类的时候可以缩小。

www.iming.info

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏跟着阿笨一起玩NET

VB.NET自我总结语法

1161
来自专栏跟着阿笨一起玩NET

VB.NET语法小结

2672
来自专栏友弟技术工作室

golang之Struct什么是结构体struct?

最近在复习golang,学习的东西,如果不使用,很快就会忘记。所以,准备复习完golang,做一个练手的小项目,加深对golang的学习。今天开始公司,进入封闭...

6006
来自专栏机器学习入门

挑战程序竞赛系列(86):3.6极限情况(3)

挑战程序竞赛系列(86):3.6极限情况(3) 传送门:AOJ 2201: Immortal Jewels 翻译参考至hankcs: http://www....

22310
来自专栏進无尽的文章

编码篇 - 正则表达式及其相关

有时我们需要在一大段长文本中过滤出我们需要的字段,或者检验该文本是否符合要求(该文本是否是邮箱,链接,电话号码或身份证),这时候就需要用到正则表达式了,当然我们...

1212
来自专栏一个会写诗的程序员的博客

《Kotlin极简教程》第五章 Kotlin面向对象编程(OOP)一个OOP版本的HelloWorld构造函数传参Data Class定义接口&实现之写pojo bean定一个Rectangle对象封

We frequently create a class to do nothing but hold data. In such a class some s...

2344
来自专栏小樱的经验随笔

洛谷 P1598 垂直柱状图【字符串+模拟】

P1598 垂直柱状图 题目描述 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过72个字符),然后用柱状图输出每个字符在输入文件中出现的次数...

3165
来自专栏数据结构与算法

洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)

具体来说,每次比较当前后缀和\(S_0\)的lcp,如果长度\(< N\)的话就从不合法的位置继续匹配

1181
来自专栏企鹅号快讯

编写高效简洁代码的那些招式1

高效的代码,每期都会给大家介绍一下编码的技巧,让我们代码更整洁更高效。我们会从python 语言切入,讲一讲如何写的代码更pythonic 。Pythonic ...

1896
来自专栏数据结构与算法

3027 线段覆盖 2

3027 线段覆盖 2  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果 题目描述 Descript...

2956

扫码关注云+社区

领取腾讯云代金券