看设计模式的相关书籍也有一段时间了,一开始其实是抱着作为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设计模式--基础思想总结--父类引用操作对象的更多相关文章

  1. java设计模式--基础思想总结--抽象类与架构设计思想

    抽象类?这个东西我感觉没什么卵用啊,又不能拿来new对象,没有具体的对象的抽象类,有什么实际的意义呢?这是很多刚刚接触java抽象类语法时的第一反应(当然,包括我).确实,很多刚刚接触抽象类这个概念的 ...

  2. Java流式思想和方法引用

    目录 Java流式思想和方法引用 1. Stream流 1.1 概述 传统集合的多步遍历代码 Stream的更优写法 1.2 流式思想的概述 1.3 获取流 1.4 常用方法 ①逐一处理:forEac ...

  3. 079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象

    079 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 04 实例化对象 本文知识点:实例化对象 说明:因为时间紧张,本人写博客过程中只是对知 ...

  4. Java多态性详解 (父类引用子类对象)

    面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作准备.那么什么是多 ...

  5. Java多态性详解——父类引用子类对象

    来源:http://blog.csdn.net/hikvision_java_gyh/article/details/8957456 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实 ...

  6. java设计模式基础 - 解决某一类问题最行之有效的方法,框架是大的设计模式.

    一.单例模式(Singleton) 1.单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1>某 ...

  7. 0.0---selenium+java自动化基础01---元素定位和操作

    一.定位方法 1.通过ID定位元素:driver. findElement(By.id(value)); 2.通过元素的名称定位元素: driver. findElement(By.name( val ...

  8. 浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象

    最近在着手重构一个java UI桌面项目,发现这个项目在一开始的时候由于需求不明确,以及开发人员对swing框架不熟悉等问题造成了页面代码混乱的情况:为了能够在各个类里都可以拿到其他类的引用去进行相应 ...

  9. Java Script基础(八) Array数组对象

    一.Array数组 JavaScript中的数组也是具有相同数据类型的一个或者多个值得集合.用法和Java中的数组类似. Array对象的常用属性和方法: 属性: length:获取数组的长度: 方法 ...

随机推荐

  1. 专题:DUILIB Win32 透明效果

    Win32 透明效果相关基础知识 Layered Windows 分层窗口.这是Windows2000开始引入的概念,重新定义了窗口的Hit Testing方法,以前都是把窗口按rectangle的方 ...

  2. 每天一个Linux命令 4

    Linux系统关机命令 shutdown -h 时间 init 0 poweroff Linux系统注销命令 logout 或者是快捷键 Ctrl+d Linux系统重启命令 reboot Linux ...

  3. Java设计模式之职责型模式总结

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6548127.html 所谓职责型模式,就是采用各种模式来分配各个类的职责. 职责型模式包括 ...

  4. 高并发解决方案之Actor——第一节

    还在为状态的并发控制而痛苦吗?   还在因为数据库瓶颈而痛苦吗?   还在因为缓存的实时性控制而痛苦吗?   还在为了想分布式,但又不知道怎么下手而痛苦吗?   Actor欢迎你!!!   一.什么是 ...

  5. 对于自定义标签类中JspBody类的invoke方法的理解

    下面是javaeeAPI中对于invoke()方法的介绍: 其中的参数out是一个Writer类的对象,如果写null,就是将标签体内容写到了与此jsp相关联的JspWriter对象,也就是下面的w: ...

  6. linux之date命令详解

    date命令的用处 1.用于显示特殊的时间格式,可以用于对日志文件的命名 2.用于设置时间 ,不过这方面用的比较少,因为一般的服务器都设置的有自动同步网络时间 用法: date [OPTION]... ...

  7. VC++中经常出现的内存泄露和指针问题

    要养成良好的编程习惯,每次用new开辟的新空间马上先写好释放语句delete.指针在程序中往往有很多细节问题,比如1.指针作为返回值,某个分支中进行赋值返回,另一个分支却没有值.2.指针作为函数参数传 ...

  8. AP付款出现(-1)例外处理

    ---手工处理方法---1.根据收款编号查询事件表中的"事件ID"---2.将AP_CHECKS_ALL表中的PAYMENT_TYPE_FLAG 标记由"Q"更 ...

  9. Poptest学员之当小厨师变成测试开发工程师

    没开玩笑,这是我们的真实案例.做培训以来,各行各业转行做测试的学员见得太多了.修车的.客服的.销售的.司机的.医护的.前台的等等.职位虽然不分贵贱,但是薪资却分多少.每个人心中都有让家人和自己过上好日 ...

  10. poptest老李谈分布式与集群

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...