Java设计思想之递归继承

来源:互联网 发布:mysql 截断表 编辑:程序博客网 时间:2024/05/09 21:58

概要

最近Java老师讲了OO程序设计思想,发现自己之前有很多设计的不足之处所以打算重新整理一下这方面的内容,函数很简单接口也容易,难的就是软件的架构这也正是我们要学的

OCP原则

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

Softeware entities like classes,modules and functions should be open for extension but closed for modifications.

开闭原则的含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。

软件实体包括以下几个部分:

  • 项目或软件产品中按照一定的逻辑规则划分的模块
  • 抽象和类
  • 方法

开闭原则是为软件实体的未来事物而制定的对现行开发设计进行约束的一个原则。

 

注意:开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段了。

 

变化的类型:

  • 逻辑变化
  • 子模块变化
  • 可见试图变化

一个项目的基本路径应该是这样的:项目开发、重构、测试、投产、运维,其中的重构可以对原有的设计和代码进行修改,运维尽量减少对原有代码修改,保持历史代码的纯洁性,提高系统的稳定性。

 

开闭原则的重要性:

  • 开闭原则对测试的影响

开闭原则可是保持原有的测试代码仍然能够正常运行,我们只需要对扩展的代码进行测试就可以了。

  • 开闭原则可以提高复用性

在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被复用的可能性就越大。

  • 开闭原则可以提高可维护性
  • 面向对象开发的要求

提出问题

需求:有一个电子销售系统需要打印顾客所购买的商品的发票(Invoice),一张发票可以分成三个部分:

Ø  发票头部(Header):上面有顾客的名字,销售的日期。

Ø  发票主部:销售的货物清单,包括商品的名字(Item)、购买的数量(Units)、单价(Unit Price)、小计(Sub Total);

Ø  发票的尾部(Footer):商品的总金额(Total);

下面是打印出的发票的大致的样子:

 

**********************     INVOICE    ************************************

XYZIncorporated

Date of Sale: Sun May 26 21:42:36 EDT 2002

Item                Units       Unite Price    Subtotal

FireWheel Tire         4         $154.3       $616.92

FrontFender           1         $300.45      $300.45

 

 

Total                                        $917.37


需要提醒的是:

 

Ø  发票的头部和尾部可以有很多种可能的格式,因此系统的设计必须给出足够的灵活性,使得一个新的头部和新的尾部格式能够比较容易地插入到系统中;

Ø  同时,本系统的客户端必须可以随意地选择某一个头部格式和某一个尾部格式的组合并与主部格式结合起来。


问题分析

我们在超市买东西的时候只要刷一下商品就会自动在电脑里存储,最后打印,我们可以在测试类里通过new一个对象的方式来模仿,那么我们就要把重点放在如何使程序符合OCP原则并且尽量使他更灵活更简练美观,这里有一种垂直继承关系,也就是递归的继承,我们子类继承父类却与父类关联(子类里有父类的对象),这样在子类里调用使用父类对象的方法就可以实现递归

类图



虽然不是最简练的哈,我们只是分析一下这种设计方法
Header是递归的基线情况,也就是递归到他递归结束并且开始打印,所以他不需要拥有父类的对象,我们在print()里面使用
{getInvoice().print;System.out.println("这个类所要打印的内容");}
这样我们就可以实现递归,也就是先调用传进来的Invoice类型的对象的print方法再打印自己的打印内容
同样的,total是用来计算总价的方法,我们用它的返回值进行递归调用就可以算出之前所有的价格
{
return getSubtotal()+getInvoice().total();
}
这样也实现了递归调用,当然,终点还在Header,因为他没有getInvoice().total()部分

总结

综上,我们知道通过这种垂直结构可以灵活的控制这个发票,无论是新加一个法语的发票头或者日语的发票尾或是任意的商品我们都可以轻松完成任务并且不对源代码进行修改,不过这个设计模式还是比较难的,所以大家有什么好的想法和新的方法可以与我联系,我们一起探讨哈~


0 0
原创粉丝点击