Java面向对象设计原则


1. 面向抽象原则

1.1 抽象类

特点:

        1.抽象类中的abstract方法可有可无,也可以有非abstract方法

        2.抽象类不能用new创建对象

        3.抽象类的非抽象子类必须重写父类的abstract方法

        4.作为向上转型对象。抽象类不能创建对象,但可以让抽象类的对象成为其非抽象子类的向上转型对象,调用子类的方法

[java] view plain copy
 print?
  1. abstract class A {  
  2.     public abstract int add(int x,int y);  
  3. }  
  4.   
  5. class B extends A {  
  6.     public int add(int x, int y) {  
  7.         return x+y;  
  8.     }  
  9. }  
  10.   
  11. public class App {  
  12.     public static void main(String[] args) {  
  13.         A a = new B();  
  14.         System.out.println(a.add(34));  
  15.     }  
  16. }  

1.2 接口

特点:

        1.接口中只能有public权限的abstract方法,不能有非abstract方法

        2.接口由类去实现,并且必须重写接口中的abstract方法

        3.接口回调。把实现接口的类的对象的引用赋给该接口声明的接口变量,那么此接口变量就可以调用被类实现的接口中的方法

[java] view plain copy
 print?
  1. interface Com {  
  2.     public abstract int sub(int x,int y);  
  3. }  
  4.   
  5. class ComImp implements Com {  
  6.     public int sub(int x, int y) {  
  7.         return x-y;  
  8.     }  
  9. }  
  10.   
  11. public class App {  
  12.     public static void main(String[] args) {  
  13.         Com com = new ComImp();  
  14.         System.out.println(com.sub(34));  
  15.     }  
  16. }  

1.3 面向抽象

        所谓面向抽象编程,就是指当设计一个类时,不该让类面向具体的类,而是面向抽象类或接口,即所设计的类中的重要数据是抽象类或接口声明的变量,而不是具体声明的变量。

        例如,现在有一个Circle类,有一个getArea()方法计算圆的面积:

Circle.Java

[java] view plain copy
 print?
  1. public class Circle {  
  2.     double r;  
  3.     Circle(double r) {  
  4.         this.r = r;  
  5.     }  
  6.     public double getArea() {  
  7.         return(3.14*r*r);  
  8.     }  
  9. }  

        现在要设计一个Pillar类(柱体类),有一个getVolume方法计算体积

Pillar.java

[java] view plain copy
 print?
  1. public class Pillar {  
  2.     Circle bottom;  //将Circle对象作为成员  
  3.     double height;  
  4.     public Pillar(Circle bottom, double height) {  
  5.         this.bottom = bottom;  
  6.         this.height = height;  
  7.     }  
  8.     public double getVolume() {  
  9.         return bottom.getArea()*height;  
  10.     }  
  11. }  
        现在来分析Pillar类,bottom是用具体类Circle类声明的变量,若用户需求不变化,则Pillar类可以这样设计。但如果用户希望求底是三角形的柱体的体积,显然上述Pillar类不能应对这种需求。

        因此需要重新设计Pillar类,这时不需要关心底是什么形状,而应该关心底是否有计算面积的方法。所以底不应该是某个具体类声明的变量,这样才能应对不同的需求。

接下来重新设计PIllar类。 首先设计一个抽象类(或接口)Geometry(几何),有一个抽象的getArea()方法。

Geometry.java

[java] view plain copy
 print?
  1. public abstract class Geometry {  
  2.     public abstract double getArea();  
  3. }  
        这样设计以后,Pillar类就不再依赖具体类,而是面向Geometry类,即Pillar类中的bottom是抽象类Geometry声明的变量。

Pillar.java

[java] view plain copy
 print?
  1. public class Pillar {  
  2.     Geometry bottom;    //bottom是抽象类Geometry声明的变量  
  3.     double height;  
  4.     public Pillar(Geometry bottom, double height) {  
  5.         this.bottom = bottom;  
  6.         this.height = height;  
  7.     }  
  8.     public double getVolume() {  
  9.         return bottom.getArea()*height;  
  10.     }  
  11. }  
        接下来就是让Circle和Rectangle(矩形)继承抽象类Geometry,并重写getArea()方法。

Circle.java

[java] view plain copy
 print?
  1. public class Circle extends Geometry  {  
  2.     double r;  
  3.     Circle(double r) {  
  4.         this.r = r;  
  5.     }  
  6.     public double getArea() {  
  7.         return(3.14*r*r);  
  8.     }  
  9. }  

Rectangle.java

[java] view plain copy
 print?
  1. public class Rectangle extends Geometry {  
  2.     double length;  
  3.     double width;  
  4.     public Rectangle(double length, double width) {  
  5.         this.length = length;  
  6.         this.width = width;  
  7.     }  
  8.     public double getArea() {  
  9.         return length*width;  
  10.     }  
  11. }  

        现在就可以用Pillar创建具有矩形底或圆形底的柱体了。

App.java

[java] view plain copy
 print?
  1. public class App {  
  2.     public static void main(String[] args) {  
  3.         Pillar pillar;  
  4.         Geometry bottom;  
  5.           
  6.         bottom = new Rectangle(10050);  
  7.         pillar = new Pillar(bottom, 50);  
  8.         System.out.println("矩形底的柱体的体积:" + pillar.getVolume());  
  9.           
  10.         bottom = new Circle(50);  
  11.         pillar = new Pillar(bottom, 50);  
  12.         System.out.println("圆形底的柱体的体积:" + pillar.getVolume());  
  13.     }  
  14. }  

        通过面向抽象来设计Pillar类,使得Pillar类不再依赖具体类,因此每当系统增加Geometry的子类时,比如增加一个Triabgle子类,那么不需要修改Pillar类的任何代码,就可以使用Pillar创建出具有三角形底的柱体。

2. 开-闭原则

        所谓“开-闭原则“(Open-Closed Principle)就是让设计对扩展开放,对修改关闭。本质就是指当一个设计中增加新的模块时,不需要修改现有的模块。在给出一个设计时,应当首先考虑到用户需求的变化,将最有可能变化的部分设计为对扩展开放,而设计的核心部分是精心考虑后确定下来的,应该对修改关闭,即不能因为用户需求的改变而修改。


3. 多用组合少用继承原则

方法复用的两种最常用的技术就是类继承和对象组合。

3.1 继承与复用

        子类通过继承父类可以复用父类的方法

优点:

        1.子类在需要的时候可以重写父类的方法,易于修改或扩展那些被复用的方法

缺点:

        1.无法在运行期间改变从父类继承的方法的行为

        2.继承是强耦合的关系,即当父类的方法的行为改变时,必然导致子类相应方法改变

        3.通过继承复用也称为“白盒”复用,这样就是说父类的内部细节对于子类而言是可见的

3.2 组合与复用

        一个类将其它对象作为自己的组成部分,即Has-A,这样就可以通过委托其它对象调用其方法来达到复用的目的。

优点:

        1.组合复用称为“黑盒”复用,即当前对象对所包含对象的具体细节是不可见的

        2.组合是弱耦合的关系,即修改所包含的对象的类的代码,不必修改当前类的代码

        3.当前对象可以在运行时动态指定所包含的对象

缺点:

        1.导致系统中对象过多

        2.要组合多个对象时,必须仔细地对接口进行定义

4. 高内聚-低耦合原则

        高内聚:类中的方法是一组相关的行为

        低耦合:尽量不要让一个类含有太多其它类的实例引用,以避免“牵一发而动全身”

                                                                                  文章转载自aylhay


阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页