【设计模式之美】<Reading Notes>继承与组合

继承缺点
继承是面向对象的四大特性之一,用来表示类之间的 is-a 关系,可以解决代码复用的问题。虽然继承有诸多作用,但继承层次过深、过复杂,也会影响到代码的可维护性。在这种情况下,我们应该尽量少用,甚至不用继承.
使用组合替换继承
继承主要有三个作用:表示 is-a 关系,支持多态特性,代码复用。而这三个作用都可以通过组合、接口、委托三个技术手段来达成。

设计一个关于鸟的类,使用组合、接口、委托完成

定义为一个抽象类 AbstractBird,麻雀、鸽子、乌鸦等,都继承这个抽象类。由于不是所有鸟都会飞,所以不是所有鸟都有fly()这个方法。
我们可以从鸟会不会飞、会不会叫来对鸟进行划分。两个行为搭配起来会产生四种情况:会飞会叫、不会飞会叫、会飞不会叫、不会飞不会叫。如果假如新行为,我们可能还需要继续构建更加细分的抽象类,这样就比较麻烦。继承层次过深、继承关系过于复杂会影响到代码的可读性和可维护性。
可以利用组合(composition)、接口、委托(delegation)三个技术手段解决这个问题。
接口表示具有某种行为特性:
可以定义一个 Flyable 接口,只让会飞的鸟去实现这个接口。
对于会叫、会下蛋这些行为特性,我们可以类似地定义 Tweetable 接口、EggLayable 接口。
1、定义接口

public interface Flyable { void fly();
}
public interface Tweetable { void tweet();
}
public interface EggLayable { void layEgg();
}

2、通过多个接口实现多个特性:鸵鸟不会飞,但是会叫会下蛋,所以只有两个接口。注意,mplements 是实现多个接口, 接口的方法一般为空的, 必须重写才能使用 。

public class Ostrich implements Tweetable, EggLayable {//鸵鸟 //... 省略其他属性和方法... @Override public void tweet() { //... } @Override public void layEgg() { //... }
}

3、接口只声明方法,不定义实现。也就是说,每个会下蛋的鸟都要实现一遍 layEgg() 方法,并且实现逻辑是一样的,这就会导致代码重复的问题。
可以针对三个接口定义三个实现类

实现了 fly() 方法的 FlyAbility 类、
实现了 tweet() 方法的 TweetAbility 类、
实现了 layEgg() 方法的 EggLayAbility 类。

public interface Flyable { void fly();}
public class FlyAbility implements Flyable { @Override public void fly() { //... }
}
//省略Tweetable/TweetAbility/EggLayable/EggLayAbility

然后,通过组合和委托技术来消除代码重复:

public class Ostrich implements Tweetable, EggLayable {//鸵鸟 private TweetAbility tweetAbility = new TweetAbility(); //组合 private EggLayAbility eggLayAbility = new EggLayAbility(); //组合 //... 省略其他属性和方法... @Override public void tweet() { tweetAbility.tweet(); // 委托 }@Override public void layEgg() { eggLayAbility.layEgg(); // 委托 }
}

由于对Java不太熟悉,可能还需要关注一下这个知识点:
extends和implements区别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scala中何时使用下划线_在Scala中使用下划线

scala中何时使用下划线Underscore (_) character is reserved in Scala and has multiple usages in the programming language. Based on functions that use the underscore have the following usages: 下划线(_)字符在Scala中保留,并且在编程语言中有多种用法。…

如何利用C#编写网页投票器程序 如何使用代理来投票 代理IP来投票

一、前言看个图,了解下投票的过程。提交投票信息投票页 ――――――――>投票信息处理页反馈投票结果(请求页)<―――――――(响应页)一般情况下,填写投票信息,然后点提交按钮发送到响应页,这…

【设计模式之美】<Reading Notes>贫血模型与充血模型

小知识 需要了解的一些名词 1、领域驱动设计(Domain Driven Design,简称 DDD) 2、MVC 三层架构 : M 表示 Model,V 表示 View,C 表示 Controller。 它将整个项目分为三层:展示层、逻辑层、数据层…

TAFE的完整形式是什么?

TAFE:拖拉机和农用设备 (TAFE: Tractors and Farm Equipment) TAFE is an abbreviation of Tractors and Farm Equipment Limited. It is an Indian tractor manufacturer which is founded at Chennai in 1960. It is the second-largest tractor manufacturer in …

Oracle 10g 数据库的备份和还原

一、备份数据库1.在图形工具中,如sqldeveloper,pl/sqldeveloper用以下这句查找空表select alter table ||table_name|| allocate extent; from user_tables where num_rows0;2.把第一步执行得到的结果当用sql语来再次执行3.到oracle服务器上执行备份语句. 运行-cmd …

用户行为分析指导电商精细化运营

规模和利润,这两个在商业运营中最基本的指标,却在电子商务市场中遭遇了不同的待遇。前两年,几乎所有的电商企业都只追求规模,不追求利润,导 致自身的运营极其粗放,绝大多数电商公司只有两招:猛打…

【C++基础】 类模板

类模板 模板是将类中某些类型变为泛型,从而定义一个模板。 如下: 类模板的语法 直接进行对比: 泛型化之前 泛型化之后类模板的实例化 注意:只要是对类模版进行实例化,编译器就会生成一个类!&#xff0…

ruby 怎么抛异常_Ruby中的异常处理

ruby 怎么抛异常Ruby异常处理 (Ruby Exception Handling) Exceptions are abnormal conditions arising in the code segment at runtime in the form of objects. There are certain predefined Exception classes whereas we can create our exception known as Custom excep…

cocos2d-x游戏开发系列教程-中国象棋02-main函数和欢迎页面

之前两个博客讲述了象棋的规格和工程文件之后,我们继续深入的从代码开始学习cocos2dx首先从程序入口main函数开始main函数int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow) {UNREFERENCED_PARAMETER(h…

[原创]Android中的android:layout_width和android:width的区别

在android系统中&#xff0c;我们可以通过在xml资源文件中定义布局&#xff0c;一般的写法是&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"ma…

【C++基础】模板参数与模板继承

模板参数 默认类型参数 函数参数可以设定一个默认值&#xff0c;我们现在可以对类模板的类型参数设定一个默认类型。 指定泛型Stack的默认类型参数为 int template<typename T int> class Stack{... };当我们这样定义一个对象时&#xff1a; Stack<> stack;使…

UNIX标准化及实现之POSIX标准可选头文件

POSIX标准定义的可选头文件 头文件说明<aio.h>异步I/O<mqueue.h>消息队列<pthread.h>线程<sched.h>执行调度<semaphore.h>信号量<spawn.h>实时spawn接口<stropts.h>XSI STREAMS接口<trace.h>事件跟踪转载于:https://www.cnblo…

Julia中的denominator()函数

Julia| 分母()函数 (Julia | denominator() function) denominator() function is a library function in Julia programming language, it is used to get the denominator of the rational representation of the given value. denominator()函数是Julia编程语言中的库函数&a…

【C++基础】STL迭代器

已知&#xff1a; STL组成部分&#xff1a; 容器、迭代器、算法、函数对象、空间分配器 容器&#xff1a;用于保存一组数据&#xff0c;数据个体被称为元素 迭代器&#xff1a;用于遍历容器中的元素&#xff0c;容器都有自己专属的迭代器&#xff0c;只有容器才知道如何遍历自己…

用ie9浏览器若出现看视频有声音没图像的问题处理

当我们在用ie9浏览器上网想看视频时&#xff0c;有时会遇到各种问题&#xff0c;尤其是有关声音和图像的。有时候有声音没图像&#xff0c;但有时候有图像却没声音。各种问题。当遇到某些问题时&#xff0c;只要是关于网页视频的&#xff0c;一般都会选择更新网页视频播放插件&…

java架构师之路:JAVA程序员必看的15本书的电子版下载地址

java架构师之路&#xff1a;JAVA程序员必看的15本书的电子版下载地址 作为Java程序员来说&#xff0c;最痛苦的事情莫过于可以选择的范围太广&#xff0c;可以读的书太多&#xff0c;往往容易无所适从。我想就我自己读过的技术书籍中挑选出来一些&#xff0c;按照学习的先后顺序…

office数据集dslr_DSLR的完整形式是什么?

office数据集dslrDSLR&#xff1a;数码单镜反光 (DSLR: Digital Single-Lens Reflex) DSLR is an abbreviation of digital single-lens reflex. It alludes to a digital camera which with the sensor of digital imaging merges optics and mechanism of single-lens reflex…

envs\TensorFlow2.0\lib\site-packages\tensorflow\python\framework\dtypes.py:516: FutureWarning 解决方案

import tensorflow后的完整报错&#xff1a; D:\Anaconda3\envs\TensorFlow2.0\lib\site-packages\tensorflow\python\framework\dtypes.py:516: FutureWarning: Passing (type, 1) or ‘1type’ as a synonym of type is deprecated; in a future version of numpy, it will b…

转义序列

转义序列描述\n换行符\r回车\t水平制表符\\反斜杠\$美元符\"双引号\[0-7]{1.3}八进制记法\x[0-9A-Fa-f]{1,2}十六进制记法转载于:https://www.cnblogs.com/cindylu520/archive/2012/07/05/2577246.html

Java动态代理模拟spring的AOP

广州疯狂软件学院拥有三大课程体系包括&#xff1a;java课程&#xff0c;android课程&#xff0c;ios课程&#xff0c;疯狂软件年终钜惠&#xff0c;报名java就业班&#xff0c;免费赠送基础班&#xff0c;名额有限&#xff0c;本月火热报名中&#xff0c;欢迎有志之士电话或者…