java设计模式--基础思想总结--父类引用操作对象
看设计模式的相关书籍也有一段时间了,一开始其实是抱着作为java三大框架的基础知识储备来学习的,不过到后来,才发现,在设计模式的一些准则装饰下,java的面向对象威力才真正地体现出来,后面的将会陆续地总结设计模式学习过程中的一些心得体会,这篇作是个人理解设计模式中的一些核心思想的简单总结,但是也是我认为在设计模式中最核心的部分思想了。
一、软件工程的设计尝试
软件工程的一些要求。在软件工程中,最基本的要求便是可重用行以及扩展性,前者要求系统的设计在代码层面可以有良好的组织结构以便公共代码可以一次编写导出调用;后者则要求软件系统在升级维护时可以在不影响前面已经编码好的模块中进行,可扩展性要求我们增加代码达到扩展效果而不是修改代码(毕竟,修改会增加bug出现的风险)。
而软件系统的以上要求,使得我们设计的软件模块要具有最终要的两个性质:高内聚而低耦合,前者说明模块功能尽量依靠自己内部完成,模块本身就可以最大化地实现自己本来的功能;低耦合和高内聚其实意思差不多,只是换了一个算法,它要求模块之间的联系尽可能地降到最低。
二、对象的封装
说到面向对象,可能没有系统思考或者学习过设计模式地人第一印象就是:面向对象=封装类。的确,以前我也是这样肤浅地认为面向对象,不就是将一对相关联的变量和方法,包装 成一个adt,也就是java中的一个类进行复用嘛,在需要的时候就new一个对象调用相应的方法不就行了,封装貌似已经可以解决很多问题了。
的确,封装为我们提供了一种代码重用以及面向对象化的抽象方式来组织我们的程序结构,它可以使得我们拥有高效的程序组织手段。然而,很多时候,仅仅依靠封装的性质是不能达到软件设计所要求的高内聚低耦合的,具体例子后面再进行举例。
三、面向抽象编程
1、利用父类引用进行操控对象。
前面说了,对象的封装不能解决软件工程的扩展性问题,下面例子便没有符合软件工程的要求了:
//有一个动物类
class Animal{
//它有各种属性
String height = null;
String foot = null;
//....其他属性 //还有一些方法
public void run(){
System.out.println("animal run method");
}
public void eat(){
System.out.println("animal eat method");
}
}
//下面有一个cat继承了animal类
class Cat extends Animal{
//覆盖掉父类方法
public void run(){
System.out.println("cat run method");
}
}
//则是一个测试类
class Test{
public void test(){
Cat cat = new Cat();
cat.run();//显然,这样可以调用cat的run方法
}
}
观察代码,在test方法中,它有以下可优化的地方:
A、cat.run并没有过多地体现出父类的作用,它仅仅是调用自己的对象引用来执行方法,当我要在test方法中执行其他动物的run方法时,还得重新写一个为某个动物而特别设定的test方法,没有达到重用代码的目的;
B、另外,如果在某个时候,该test方法中的动物不在是cat了(例如我加突然不想养猫了而换成狗),这时还需要改变硬编码(当然可以利用A的方法新建特定的test方法)
C、这段代码没有体现面向对象一个很重要的性质:多态。既然子类都可以进行run的重写操作,就应该在代码中表现出不同子类的同样方法会表现出不同的行为
(好吧,其实这三点归根到底就是一点:代码不可扩展,没有体现多态)
下面进行简单的改写(仅仅重新写test类):
//这是一个改写后的测试类
class Test{
Animal animal = null;
//新增一个构造函数
public Test(Animal animal){
this.animal = animal;
}
public void test(){
//通过父类引用操作子类对象
animal.run();
}
}
改写后的代码具有高度的内聚性,因为Test类它本身并不依赖其他的任何动物,如果你要对Test方法执行cat对应的方法,直接在构造函数中传入cat对象即可,需要dog就传入dog就可,java的多态性质会自动帮你根据特定的类完成特定的run方法!显然,这个test类变达到了软件工程的基本要求:高内聚(只是依靠内部代码进行相应的操作),低耦合(没有依赖特定的对象,只是依赖抽象层次的animal)
所以可以有一下总结:通过操作父类的引用来控制操作子类对象可以达到多态的效果。
2、通过接口操作对象。看下面的例子:
//定义一个接口,它抽象了一种行为:飞
interface FlyAction{
public void fly();
} //bird类
class Bird extends Animal implements FlyAction{
//实现接口
public void fly() {
System.out.println("I am bird ,this is my fly methd");
}
}
//duck类
class Duck extends Animal implements FlyAction{
public void fly() {
System.out.println("I am duck ,this is my fly methd");
}
}
//类似,我们新建一个测试类
class Test{
FlyAction animalFlyAction = null;
public Test(FlyAction animalFlyAction){
this.animalFlyAction = animalFlyAction;
}
public void test(){
animalFlyAction.fly();
}
}
代码较简单,我从代码中主要传递一下的一些思想:
A、为什么将fly定义为接口,而不是直接在animal中新增一个fly方法?
因为不是所有的animal都会飞,animal中的代码必须保证所有子类都共有。由此,我们大概可以体会到实现接口与类继承的一些区别了:前者是特定行为的扩展,后者是公共行为的提取与抽象。
B、接口操作对象的优点:显然,有了上面的父类引用操作子类对象的讨论后,我们可以领悟到接口操作对象其实是类似的:通过java的多态机制实现特定实现类的调用同样的方法,而方法的实现却不相同,从而达到了高内聚低耦合的效果(也是多态的效果)。
四、总结
所以,通过上面例子,我们大概可以对面向接口编程或者说面向父类引用编程(其实更恰当地说是面向抽象编程,不过这个概念后面博客再具体讲解)有个大体的认识了:其实就是通过父类引用来操作子类对象或者通过接口引用操作对应的实现类进行代码的解耦和多态的实现。
所以,我们可以得出设计原则一:
尽量利用父类引用和接口进行对象的具体操作。
OK,设计模式的第一篇就到这里,后面的博客再整理一些更深入的思想——面向抽象编程以及封装变化的手段。
java设计模式--基础思想总结--父类引用操作对象的更多相关文章
- java设计模式--基础思想总结--抽象类与架构设计思想
抽象类?这个东西我感觉没什么卵用啊,又不能拿来new对象,没有具体的对象的抽象类,有什么实际的意义呢?这是很多刚刚接触java抽象类语法时的第一反应(当然,包括我).确实,很多刚刚接触抽象类这个概念的 ...
- Java流式思想和方法引用
目录 Java流式思想和方法引用 1. Stream流 1.1 概述 传统集合的多步遍历代码 Stream的更优写法 1.2 流式思想的概述 1.3 获取流 1.4 常用方法 ①逐一处理:forEac ...
- 079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象
079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象 本文知识点:实例化对象 说明:因为时间紧张,本人写博客过程中只是对知 ...
- Java多态性详解 (父类引用子类对象)
面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作准备.那么什么是多 ...
- Java多态性详解——父类引用子类对象
来源:http://blog.csdn.net/hikvision_java_gyh/article/details/8957456 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实 ...
- java设计模式基础 - 解决某一类问题最行之有效的方法,框架是大的设计模式.
一.单例模式(Singleton) 1.单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1>某 ...
- 0.0---selenium+java自动化基础01---元素定位和操作
一.定位方法 1.通过ID定位元素:driver. findElement(By.id(value)); 2.通过元素的名称定位元素: driver. findElement(By.name( val ...
- 浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象
最近在着手重构一个java UI桌面项目,发现这个项目在一开始的时候由于需求不明确,以及开发人员对swing框架不熟悉等问题造成了页面代码混乱的情况:为了能够在各个类里都可以拿到其他类的引用去进行相应 ...
- Java Script基础(八) Array数组对象
一.Array数组 JavaScript中的数组也是具有相同数据类型的一个或者多个值得集合.用法和Java中的数组类似. Array对象的常用属性和方法: 属性: length:获取数组的长度: 方法 ...
随机推荐
- vue入门 vue与react和Angular的关系和区别
一.为什么学习vue.js vue.js兼具angular.js和react的优点,并且剔除了他们的缺点 官网:http://cn.vuejs.org/ 手册:http://cn.vuejs.org/ ...
- 超出父视图无法点击问题hitTest
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...
- click和onclick本质的区别
原生javascript的click在w3c里边的阐述是DOM button对象,也是html DOM click() 方法,可模拟在按钮上的一次鼠标单击. button 对象代表 HTML 文档中的 ...
- Metadata Service 一个最简单的应用 - 每天5分钟玩转 OpenStack(164)
实现 instance 定制化,cloud-init(或 cloudbase-init)只是故事的一半,metadata service 则是故事的的另一半.两者的分工是:metadata servi ...
- UWP--MVVM简单计算器
namespace LBI.DataBinding { /// <summary> /// 可用于自身或导航至 Frame 内部的空白页. /// </summary> pub ...
- 构建微服务-使用OAuth 2.0保护API接口
微服务操作模型 基于Spring Cloud和Netflix OSS 构建微服务-Part 1 基于Spring Cloud和Netflix OSS构建微服务,Part 2 在本文中,我们将使用OAu ...
- 二、Fragment+RadioButton实现底部导航栏
在App中经常看到这样的tab底部导航栏 那么这种效果是如何实现,实现的方式有很多种,最常见的就是使用Fragment+RadioButton去实现.下面我们来写一个例子 首先我们先在activi ...
- Python 爬取qqmusic音乐url并批量下载
qqmusic上的音乐还是不少的,有些时候想要下载好听的音乐,但有每次在网页下载都是烦人的登录什么的.于是,来了个qqmusic的爬虫. 至少我觉得for循环爬虫,最核心的应该就是找到待爬元素所在ur ...
- JVM中GC浅解:垃圾回收的了解
1.为什么要有GC 没有GC的世界,我们需要手动进行内存管理,但是内存管理是纯技术活,又容易出错.但是我们写码的目的是为了解决业务问题,所以可以把这种纯技术活自动化,当然自动化也是有代价的. 2.垃圾 ...
- RMQ问题(线段树算法,ST算法优化)
RMQ (Range Minimum/Maximum Query)问题是指: 对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在[i,j]里的最小(大)值 ...