面向抽象原则——Java程序设计基础

一、抽象类和接口

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

代码示例:

抽象类:

public abstract class A {
     public abstract int add(int x,int y);
}

public class B extends A {
     public  int add(int x,int y) {
         return x+y;
    }
}

public class Application {
    public static void main(String args[]) {
         A a;
         a=new B();   //a是B类对象的上转型对象

         int m=a.add(3,2); //a调用子类B重写的add()方法
         System.out.println(m);  //输出结果为5
    }
}
接口:

public 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 Application {
    public static void main(String args[]) {
         Com com;
         com=new ComImp();   //com变量存放ComImp类的对象的引用

         int m=com.sub(8,2); //com回调ComImp类实现的接口方法
         System.out.println(m);  //输出结果为6
    }
}

二、面向抽象 

代码示例:

abstract class A {
	public abstract int add(int a, int b);
}

class B extends A{
	public int add(int a, int b) {
		return a*b;
	}
}

public class TestClass {

	public static void main(String[] args) {
		A a = null;	//	面向抽象原则(声明抽象类/接口对象)
		
		a = new B();    //    a是B类的上转型对象
        int m = a.add(2,3);
        System.out.println("m = "+m);
        
/*	等价于:	
		B b = new B();
		int m = b.add(2, 3);
		System.out.println("m = "+m);
*/
	}
}

 我们已经有了一个Circle类,该类创建的对象circle调用getArea()方法可以计算圆的面积。

现在要设计一个Pillar类(柱类),该类的对象调用getVolume()方法可以计算柱体的体积,Pillar类的代码如下:

public class Pillar {
    Circle  bottom;    //将Circle对象作为成员,bottom是用具体类声明的变量
    double height;
    Pillar (Circle bottom,double height) {
        this.bottom=bottom;this.height=height;
    }
    public double getVolume() {
        return bottom.getArea()*height; 
    }
}

如果不涉及用户需求的变化,上面Pillar类的设计没有什么不妥,但是在某个时候,用户希望Pillar类能创建出底是三角形的柱体。显然上述Pillar类无法创建出这样的柱体,即上述设计的Pillar类不能应对用户的这种需求。

 因此,我们在设计Pillar类时不应当让它的底是某个具体类声明的变量,一旦这样做,Pillar类就依赖该具体类,缺乏弹性,难以应对需求的变化。


下面我们将面向抽象重新设计Pillar类。首先编写一个抽象类Geometry(或接口),该抽象类(接口)中定义了一个抽象的getArea()方法,Geometry如下:

public abstract class Geometry { //如果使用接口需用interface来定义Geometry。
     public abstract double getArea();
}

 Pillar的设计不再依赖具体类,而是面向Geometry

public class Pillar {
    Geometry  bottom;  //bottom是抽象类Geometry声明的变量
    double height;
    Pillar (Geometry bottom,double height) {
        this.bottom = bottom; this.height=height;
    }
    public double getVolume() {
        return bottom.getArea()*height; 
    }
   }

CircleRectangle类都是Geometry的子类,二者都必须重写Geometry类的getArea()方法来计算各自的面积。

Circle类:

public class Circle extends Geometry {
    double r;

    Circle(double r) {
        this.r=r;
    }

    public double getArea() {
        return(3.14*r*r);
    }
}
Rectangle类:

public class Rectangle extends Geometry {
    double a,b;
    Lader(double a,double b) {
        this.a=a; this.b=b; 
    }
    public double getArea() {
        return a*b;
    }
}

 现在就可以用Pillar 类创建出具有矩形底或圆形底的柱体:

public class Application{
    public static void main(String args[]){
        Pillar pillar;
        Geometry bottom;
        bottom=new Rectangle(12,22,100);
        pillar = new Pillar (bottom,58);  //pillar是具有矩形底的柱体
        System.out.println("矩形底的柱体的体积"+pillar.getVolume());
        bottom=new Circle(10);
        pillar = new Pillar (bottom,58); //pillar是具有圆形底的柱体
        System.out.println("圆形底的柱体的体积"+pillar.getVolume());
    }
}

 Pillar不再依赖具体类,因此每当系统增加新的Geometry的子类时,比如增加一个Triangle子类,那么不需要修改Pillar类的任何代码,就可以使用Pillar创建出具有三角形底的柱体。

完整代码:

public abstract class Geometry { //如果使用接口需用interface来定义Geometry。

     public abstract double getArea();
}

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 a,b;

    Rectangle(double a,double b) {
        this.a=a; this.b=b; 
    }

    public double getArea() {
        return a*b;
    }
}

public class Pillar {

    Geometry  bottom;        //bottom是抽象类Geometry声明的变量
    double height;

    Pillar (Geometry bottom,double height) {
        this.bottom=bottom; this.height=height;
    }

    public double getVolume() {
        return bottom.getArea()*height; //bottom可以调用子类重写的getArea方法
    }
}

public class Application{
    public static void main(String args[]){

        Pillar pillar;
        Geometry bottom;

        bottom=new Rectangle(12,22);
        pillar =new Pillar (bottom,58);  //pillar是具有矩形底的柱体
        System.out.println("矩形底的柱体的体积"+pillar.getVolume());

        bottom=new Circle(10);
        pillar =new Pillar (bottom,58); //pillar是具有圆形底的柱体
        System.out.println("圆形底的柱体的体积"+pillar.getVolume());

    }
}

实例: 

编写一个手机拼装程序

请编写一个接口(或抽象类) Screen, 里面声明一个方法showScreen,返回值类型是String

编写三个类,都继承(实现上面的Screen) :

索尼Sony,实现它的showScreen方法,返回值是"索尼”

三星SAMSUNG,实现它的showScreen方法,返回值是"三星"

再编写一个接口Battery,里面声明一个方法showBattery,返回值类型是String

继承(实现) Battery,写两个类:

联想Lenovo,实现它的showBattery方法, 返回值是"联想"

诺基亚NOKIA ,实现它的showBattery方法,返回值是"诺基亚”

再编写一 个类Phone

在Phone中,组装上面的屏幕和电池,写一个方法showPhone

输出:本手机采用XX屏幕,XX电池。

主类中,请用户输入屏幕牌子,电池牌子,实例化一个Phone对象, 调用它的showPhone0方法输出屏幕和电池型号。

代码示例:


public interface Screen {
	public abstract String showScreen();
}

public String showScreen() {
		// TODO 自动生成的方法存根
		return "索尼";
	}
}

public class SAMSUNG implements Screen{

	public String showScreen() {
		// TODO 自动生成的方法存根
		return "三星";
	}
}


public interface Battery {
	public abstract String showBattery();
}

public class Lenovo implements Battery{

	@Override
	public String showBattery() {
	
		return "联想";
	}
}

public class NOKIA implements Battery{

	@Override
	public String showBattery() {
	
		return "诺基亚";
	}
}


public class Phone {
//  封装
	private Screen button1;
	private Battery button2;
	
//	利用对象类的构造函数给接口的上转型对象进行赋值
	public Phone(Screen button1, Battery button2) {
		this.button1 = button1;
		this.button2 = button2;
	}
	
	public void showPhone() {
		System.out.println("本手机采用"+button1.showScreen()+"屏幕,"+button2.showBattery()+"电池");
	}
}


import java.util.Scanner;
public class MainClass {

	@SuppressWarnings("resource")
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Screen button1 = null;	
		Battery button2 = null;
		Phone p;	//	声明对象类对象
		System.out.println("请输入屏幕牌子:");
		String s1 = new Scanner(System.in).nextLine();
		if(s1.equals("索尼"))
		{
			button1 = new Sony();
		}
		else if(s1.equals("三星"))
		{
			button1 = new SAMSUNG();
		}
		System.out.println("请输入电池牌子:");
		String s2 = new Scanner(System.in).nextLine();
		if(s2.equals("联想"))
		{
			button2 = new Lenovo();
		}
		else if(s2.equals("诺基亚"))
		{
			button2 = new NOKIA();
		}
		
		p = new Phone(button1, button2);
		p.showPhone();
	}

}

猜你喜欢

转载自blog.csdn.net/Mr_Morgans/article/details/121409216