面向对象四大设计原则

面向抽象原则

1.1 抽象类


特点:
1.抽象类中的abstract方法可有可无,也可以有非abstract方法
2.抽象类不能用new创建对象
3.抽象类的非抽象子类必须重写父类的abstract方法
4.作为向上转型对象。抽象类不能创建对象,但可以让抽象类的对象成为其非抽象子类的向上转型对象,调用子类的方法

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

1.2 接口


特点:
1.接口中只能有public权限的abstract方法,不能有非abstract方法
2.接口由类去实现,并且必须重写接口中的abstract方法
3.接口回调。把实现接口的类的对象的引用赋给该接口声明的接口变量,那么此接口变量就可以调用被类实现的接口中的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Com {
public abstract int sub(int x,int y);
}
class ComImp implements Com {
public int sub(int x, int y) {
return x-y;
}
}
public class App {
public static void main(String[] args) {
Com com = new ComImp();
System.out.println(com.sub(3, 4));
}
}

1.3 面向抽象


所谓面向抽象编程,就是指当设计一个类时,不该让类面向具体的类,而是面向抽象类或接口,即所设计的类中的重要数据是抽象类或接口声明的变量,而不是具体声明的变量。
例如,现在有一个Circle类,有一个getArea()方法计算圆的面积:
1
2
3
4
5
6
7
8
9
public class Circle {
double r;
Circle(double r) {
this.r = r;
}
public double getArea() {
return(3.14*r*r);
}
}

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

1
2
3
4
5
6
7
8
9
10
11
public class Pillar {
Circle bottom; //将Circle对象作为成员
double height;
public Pillar(Circle bottom, double height) {
this.bottom = bottom;
this.height = height;
}
public double getVolume() {
return bottom.getArea()*height;
}
}

现在来分析Pillar类,bottom是用具体类Circle类声明的变量,若用户需求不变化,则Pillar类可以这样设计。但如果用户希望求底是三角形的柱体的体积,显然上述Pillar类不能应对这种需求。
因此需要重新设计Pillar类,这时不需要关心底是什么形状,而应该关心底是否有计算面积的方法。所以底不应该是某个具体类声明的变量,这样才能应对不同的需求。
接下来重新设计PIllar类。 首先设计一个抽象类(或接口)Geometry(几何),有一个抽象的getArea()方法。
Geometry.java
public abstract class Geometry {
public abstract double getArea();
}

这样设计以后,Pillar类就不再依赖具体类,而是面向Geometry类,即Pillar类中的bottom是抽象类Geometry声明的变量。
Pillar.java

1
2
3
4
5
6
7
8
9
10
11
public class Pillar {
Geometry bottom; //bottom是抽象类Geometry声明的变量
double height;
public Pillar(Geometry bottom, double height) {
this.bottom = bottom;
this.height = height;
}
public double getVolume() {
return bottom.getArea()*height;
}
}

接下来就是让Circle和Rectangle(矩形)继承抽象类Geometry,并重写getArea()方法。
Circle.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Circle extends Geometry {
double r;
Circle(double r) {
this.r = r;
}
public double getArea() {
return(3.14*r*r);
}
}
public class Rectangle extends Geometry {
double length;
double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
public double getArea() {
return length*width;
}
}

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

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

通过面向抽象来设计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. 高内聚-低耦合原则


高内聚:类中的方法是一组相关的行为
低耦合:尽量不要让一个类含有太多其它类的实例引用,以避免“牵一发而动全身”

文章目录
  1. 1. 面向抽象原则
    1. 1.1. 1.1 抽象类
    2. 1.2. 1.2 接口
    3. 1.3. 1.3 面向抽象
  2. 2. 2. 开-闭原则
  3. 3. 3. 多用组合少用继承原则
    1. 3.1. 3.1 继承与复用
    2. 3.2. 3.2 组合与复用
  4. 4. 4. 高内聚-低耦合原则