前言:
前言:java这种面向对象的的语言其实是很符合人的生活思维模式的,因为它以对象作为自己的研究对象,所谓“万物皆对象”。一个人、一颗苹果、一只蚂蚁都是对象。所以它的设计原则和设计模式都是围绕对象思考之后凝练出来的思想精粹,都具有时间上的稳定性。本节我们就来聚焦java的设计原则,一探java程序设计原则的内幕。
一:单一职则原则
1.1解释:指的是Java在进行类设计的时候,应该让一个类只完成一件具体的事,承担自己单一的职责。只能由一种原因引起自身的变化,也就是说它的功能单一性。具体的属性、方法的设计应该围绕的是如何去完成这个单一的职责,而不管其他功能。
1.2:示例
示例:假如我们现在来完成给用户发邮件这件事,我们来定义这个类,那么这个类就只管发邮件这个动作,至于发送给谁邮件,发送的内容是什么,我们可以用Mail类来完成处理,这个SendMail类根本不去维护这些东西
public class Mail{ private String address;//发送的地址 private String content;//发送的内容 private Person Person;//发送给谁 }
public class SendMail{ //发送邮件 public void send(){
//send mail detail
} }
引申意义:
可以把一个类理解为一个人,社会是由人构成的,社会可以理解为一个大的容器,人是其中的构件。每个人应该让自己的职业单一,尽量只完成自己的任务,拥有“专注”的精神。专攻一个行业,黑客与画家中有这样一句话:“一个人想在某个领域有所建树,必须投入自己所有的全部精力”。让自己全身心投入到一件事中,这样才有可能取得一定的业绩。毕竟一个人的精力是有限的。
二:依赖倒置原则:
2:1:解释:高层组件应该依赖于抽象而不是具体,即应该进行面对接口编程。依赖的成员变量和参数都应该是抽象的而不是具体的。
引申意义:如果映射到现实世界中,可以发现这种现象随处可见。比如在一家企业公司里,高层领导说的话大多是笼统而概念化的。不指向具体的事物,只是泛泛而谈。这样通过层层往下具体的分工,分到每个人身上完成具体的任务,有底层的人物去完成具体的细节
2.2:示例:假如某电商网站正在搞促销,我们需要一个价格的观察器来观察它的价格变化,这个时候我们最好定义一个具体的观察者并且实现Observer接口,这样做的好处就是减少了代码量,可以复用Observer提供的方法。并且维护一个Set集合,这里并不去用具体的集合,成员变量最好是抽象的,这样在对子类进行实现的时候,我们可以自由选择,而不是写死。增加了程序的灵活度,比如后期我们需要对观察的用户进行排序,这样就可以在方法中进行TreeSet的实现,如果不需要为了更高的性能,可以用HashSet作为具体实现:
public class PriceObserver implements Observer
{
private Set<Users> observers;
}
三:里氏替换原则
3.1解释:凡是父类出现的地方都可以用子类进行代替,并且原功能没有发生变化,即所有引用基类的地方必须能透明地使用其子类的对象。
3.2:示例:这里就不得不提java的多态了,即父类引用指向子类对象,我们来定义个动物类,它具有飞和跑的功能,我们是实现一个子类,叫pig,不过这里就有一个问题了,猪它不会飞(无法实现fly方法),怎么办呢?
public class Animal { public absract void fly(); public absract void run(); } public class pig extends Animal { @override public void fly(){ } @override public void run(){ } }
修正后如下:为了让父类的方法更具有适用性和伸缩度,我们应该添加一个参数来判断它时候是否能进行:
public class Animal
{
public absract void fly(boolean able);
public absract void run(boolean able);
}
简单而言它有以下几个我们必须遵守的:
- 子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
3.3:引申意义:这也应了一句话:长江后浪推前浪,前浪死在沙滩上。儿子继承了父亲的衣钵,一般拥有父亲的能力。当然这句话并不严谨,我们看到很多故事中,一般父亲做的职业,都不会让儿子继续干。关于这里我想从另一方面去理解,那就是学习能力。可以把老师理解为父类,学生理解为子类,子类去实现父类的方法,提高自己的学习能力,通过最后的学习拥有老师的知识和财富。
四:迪米特原则
4.1:解释:一个类应该尽量的封装自己,与自己的朋友类打交道,一般朋友类都是成员变量和参数,非朋友类是局部参数.
4.2:示例:假如我们来设计一个设备开启的方法封装类,它内部含有多个细节,比如接通电源、开启设备的运行状态、开启设备的屏幕显示、开启声音驱动,这时候我们就要尽可能的封装它,向外暴露出简单易用的api:
public class OpenDevice { private MediaHelper mediaHelper; private void openPowerSource(){ System.out.println("开启电源..."); } public void open(){ //只向外暴露总的开启方法 而不暴露具体的开机细节 openPowerSource(); mediaHelper.openMedia(); } }
public class MediaHelper { //朋友类 private void openScreen(){ System.out.println("开启屏幕"); } private void openSound(){ System.out.println("开启声音"); } public void openMedia(){//封装两个private方法,将其权限增大为public向外暴露 openScreen(); openSound(); } }
简单而言它有以下几个我们必须遵守的:
- 自己本类的成员变量尽量设置为private的,降低外界的访问权限
- 自己本类的方法尽量为private的,只暴露业务逻辑上的改口方法,而不是技术细节内部的方法
- 如果朋友类有间接的引用,这时候应该隐藏间接引用,不从中间暴露。我们可以新增一个中间类来管理所有的需要类
引申意义:一个人应该尽量的完善自己,尽量与自己朋友之间来往,不要过渡的依赖别人,应该保证自己的独立性,或者拒绝与外部陌生人打交道。这是“安全”策略,实现与外部的连接很有可能会有一定的风险。就好比有些孩子本性纯良,被一些社会上的不三不四的人带着误入歧途(比我的表弟)。当然并不能理解为封心,拒绝与外部交流。这样只会生活在一个狭小的区域范围内,看不到外面的风景,会让自己的视野变的窄而短。从而目光短浅。软件设计中有一个追求的特性是:高内聚,低耦合。一个人应该尽可能的完善自己,而尽量减少与其他人的联系。有句话叫做“你若盛开,蝴蝶自来”。这里的盛开可以理解为“内聚”性。让自己的能力聚集起来,绽放出最美丽的自己。
五:接口隔离原则
解释:一个接口尽可能的功能单一化,不要承担过多的责任。
示例:这里可以用spring的BeanFactory类来说明问题:
beanFactory 是Spring bean容器的根接口.提供获取bean,是否包含bean,是否单例与原型,获取bean类型,bean 别名的api.其核心功能在于bean的管理上
AutowireCapableBeanFactory 添加集成其他框架功能.如果集成WebWork则可以使用Spring对Actions等进行管理.主要用于其他地方引用BeanFactory
HierarchicalBeanFactory 提供父容器的访问功能,主要功能在于父容器的操作上
ConfigurableBeanFactory 如名,提供factory的配置功能,主要负责配置bean
ConfigurableListableBeanFactory 集大成者,提供解析,修改bean定义,并与初始化单例.
ListableBeanFactory 提供容器内bean实例的枚举功能.这边不会考虑父容器内的实例.
可以看到BeanFactory向下的接口中都有各自的职责,之间分别划分具体的功能和职责,互不影响,每个接口完成自己本身的任务。
应该遵守以下几条原则:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性,但是如果过小,则会造成接口数量过多,使其太过复杂,所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互,在有限的范围内使接口用最少的方法去完成最多的事情。
引申意义:这点其实和职责单一有异曲同工之秒。不过一个说的是类,一个说的是接口。接口和类是两个不同的概念,一个是实体东西,一个是抽象功能概括。这里就想多谈谈职责这个问题,而类中我谈的是职业。职责中自己应该具体专攻一方面,而不是太多的东西,上文提到过我们的精力有限,承担的具体职责也是有限的,应该尽可能的让自己承担少,这样才能更好的完成目前的工作。除非有多余的精力,才可以去探索各种东西。
六:开闭原则
Java:对扩展开放,对修改闭合。对于一个系统来说,应该拥有一套良好的扩展性,方便进行功能的扩展,而不会影响到具体的其他组件。任何事情都要防患于未然。当进行功能的扩展时候,尽量不要修改原代码,不要改动原来的东西。
简而言之,它需要我们做出以下:
1:通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
2:参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
3:抽象层尽量保持稳定,一旦确定即不允许修改。
引申意义:我从这点悟到的是,和一个人交流的时候应该做的是不要随意批判一个人,不要尝试去改变一个人,我没有那么大的权利,也没有那么大的能力去指指点点别人的生活。尽量的不要修改,如果想可以原基础上进行其他方面的扩展。比如对兴趣的延伸,新大陆的开展。毕竟每个人都不是傻子,每个人都拥有自己的生活空间,不要擅自的去修改。还有另一方面,一个人应该不断的扩展自己的能力。
总结
本篇博文主要介绍了java的程序设计的六大原则,记住软件设计的一个核心思想就是:高内聚、低耦合。无论怎样的手段和措施,我们都是在朝着这两个目标发展。在平时的程序开发过程中,我们应该严格按照这些设计原则,这样设计出来程序的更加具有复用性和健壮性的特点,也对我们的程序开发更加具有指导性。