面向对象五大原则_1.单一职责原则&2.里氏替换原则

来源:互联网 发布:股票网上开户软件 编辑:程序博客网 时间:2024/06/07 12:14

单一职责原则:Single Responsibility Principle (SRP)

一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。

T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。也就是说职责P1和P2被耦合在了一起。
原因是职责扩散:因为某种原因,某一职责被分化为颗粒度更细的多个职责了

例如Iphone接口,打电话分为四个过程,拨号,通话,回拨,挂机。


这样子貌似没错,但是仔细想一想扩展性和变更,你会发现,如果将来升级,要转化为数字电话,那么通话要重新写,拨号也是。
这样一来的话,需要一种更好的设计,不管一种方法如何变化,另一种不管。这就是职责单一原则。 
思路如下: Iphone这个接口有俩个职责,一个是协议管理,一个是数据传输。
一个负责传输数据,不管什么数据,基于什么版本,而另一个负责拨号和挂机,拨号只负责能接通就行。

这样的好处: 协议管理和数据传送分开,如果将来科技进步,那么就减少了因为变更而引起的工作量。可维护性和可读性提高了。

再来一个例子:  修改信息  


修改后:



里氏替换原则: Liskov Substitution Principle,LSP

继承的优缺点
优点:代码共享,重用性,可扩展性
缺点:降低了代码的灵活性,增加了耦合性(父变子则变)

 : 父类就是为了解决子类们基础问题而存在,好比父类就是大地,而子类就是大地上所有植物,父类就解决了土地,水的问题。

 

1.子类继承父类的成员变量

  当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:

  1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;

  2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

  2.子类继承父类的方法

  同样地,子类也并不是完全继承父类的所有方法。

  1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;

  2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。

  注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。(后面会讲到)

  3.构造器

  子类是不能够继承父类的构造器,但是要注意的是,如果父类的构造器都是带有参数的,则必须在子类的构造器中显示地通过super关键字调用父类的构造器并配以适当的参数列表。如果父类有无参构造器,则在子类的构造器中用super关键字调用父类构造器不是必须的,如果没有使用super关键字,系统会自动调用父类的无参构造器。



   原则1:子类必须完全实现父类的方法
        就如上面所说的,假如大地的子类玉兔,这个东西既不需要土地和水,却继承了大地,那么这是不合理的。子类必须完全实现父类的方法就是为了代码复用。    
       
    
   原则2:子类可以有自己的个性
        在子类出现的地方,父类未必可以胜任。
        子类在继承的同时可以扩展出其他方法和属性。万物生长,基于大地。
    
   原则3:覆盖式实现父类的方法时输入参数可被放大
        首先理解重写和重载的区别: 
                重载:方法名相同,参数不同。 
                重写:方法名相同,参数相同。

分析:覆盖式实现父类方法其实就是重载,如果子类中输入参数被放大,那么父类那部分代码就没有浪费,这句话说的很晦涩,的确刚刚学的时候想了好久,后来再看了一下原则就释然了,代码重用!每个方法必须有所用处,父类中的参数范围虽然没有子类的大,子类的重载是为了扩展,弥补了父类的不足。一般来说,是不会去重载的。
如果反过来,如果子类的参数范围比父类要小,相当于子类方法中有俩个方法,一个是父类的方法,一个是子类的,父类参数范围大,子类范围小。有父类的地方子类却不能使用,这个已经违背了原则。

 : 重载就是将父类的类名称改为子类名,再加一个方法名相同,参数不同的方法。
      重写就是将父类的类名称改为自类名,再修改一下被重写的方法。

例子: 
Father 类
public class Father { public Collection doSomething(Map map){  System.out.println("父类:Map 转集合");  return map.values(); }}

Son 类

public class Son extends Father { public Collection doSomething(HashMap map) {  System.out.println("子类:Hashmap 转集合");  return map.values(); }}

测试类

public static void main(String[] args) {  Son f=new Son();      //俩个方法 一个  HashMap h=new HashMap();  f.doSomething(h);  //子类 }

结果:

子类:Hashmap 转集合 


参考书籍:

《设计模式之禅》

参考文章: 

http://www.cnblogs.com/dolphin0520/p/3803432.html
http://www.cnblogs.com/xiaoao808/archive/2008/03/11/1100886.html



我是菜鸟,我在路上。

0 0
原创粉丝点击