1. 面向抽象原则
1.1 抽象类
特点:
1.抽象类中的abstract方法可有可无,也可以有非abstract方法
2.抽象类不能用new创建对象
3.抽象类的非抽象子类必须重写父类的abstract方法
4.作为向上转型对象。抽象类不能创建对象,但可以让抽象类的对象成为其非抽象子类的向上转型对象,调用子类的方法
- 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.接口回调。把实现接口的类的对象的引用赋给该接口声明的接口变量,那么此接口变量就可以调用被类实现的接口中的方法
- 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()方法计算圆的面积:
Circle.Java
- public class Circle {
- double r;
- Circle(double r) {
- this.r = r;
- }
- public double getArea() {
- return(3.14*r*r);
- }
- }
现在要设计一个Pillar类(柱体类),有一个getVolume方法计算体积
Pillar.java
- 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类,这时不需要关心底是什么形状,而应该关心底是否有计算面积的方法。所以底不应该是某个具体类声明的变量,这样才能应对不同的需求。
接下来重新设计PIllar类。 首先设计一个抽象类(或接口)Geometry(几何),有一个抽象的getArea()方法。
Geometry.java
- public abstract class Geometry {
- public abstract double getArea();
- }
Pillar.java
- 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.java
- public class Circle extends Geometry {
- double r;
- Circle(double r) {
- this.r = r;
- }
- public double getArea() {
- return(3.14*r*r);
- }
- }
Rectangle.java
- 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
- 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. 高内聚-低耦合原则
高内聚:类中的方法是一组相关的行为
低耦合:尽量不要让一个类含有太多其它类的实例引用,以避免“牵一发而动全身”