首页 > 代码库 > 面向对象五大原则_1.单一职责原则&2.里氏替换原则

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


单一职责原则: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)对于子类能够继承的父类成员变量,假设在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。假设要在子类中訪问父类中同名成员变量,须要使用superkeyword来进行引用。

  2.子类继承父类的方法

  相同地,子类也并非全然继承父类的全部方法。

  1)可以继承父类的public和protected成员方法。不可以继承父类的private成员方法;

  2)对于父类的包訪问权限成员方法,假设子类和父类在同一个包下,则子类可以继承。否则,子类不可以继承。

  3)对于子类能够继承的父类成员方法。假设在子类中出现了同名称的成员方法,则称为覆盖。即子类的成员方法会覆盖掉父类的同名成员方法。

假设要在子类中訪问父类中同名成员方法,须要使用superkeyword来进行引用。

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

  3.构造器

  子类是不可以继承父类的构造器,可是要注意的是。假设父类的构造器都是带有參数的,则必须在子类的构造器中显示地通过superkeyword调用父类的构造器并配以适当的參数列表。假设父类有无參构造器,则在子类的构造器中用superkeyword调用父类构造器不是必须的,假设没有使用superkeyword,系统会自己主动调用父类的无參构造器。



   原则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



我是菜鸟,我在路上。

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