1.面向抽象編程(重在理解)
在設計程序時,經常會使用abstract類,其原因是,abstract類只關心操作,而不管行這些操作具體的實現細節,可以使程序得設計者把主要精力放在程序的設計上,而不必拘泥於細節的實現(這些細節可以留給子類的設計者),即避免設計者把大量的時間和精力花費在具體的算法上。
在設計一個程序時,可以通過在abstract類中聲明若干個abstract方法,表明這些方法在整個系統設計中的重要性,方法體的內容細節由它的非abstract子類去完成。
所謂面向抽象編程,是指當設計某種重要的類時,不讓該類面向具體的類,而是面向抽象類,即所設計類中的重要數據是抽象類聲明的對象,而不是具體類聲明的對象。
下面通過一個簡單的問題來說明面向抽象編程的思想。
abstract class Gemoetry{
public abstract double getArea();
}
class Circle extends Gemoetry{
double r;
Circle(double r){
this.r=r;
}
public double getArea() {
return 3.14*r*r;
}
}
class Rectangle extends Gemoetry{
double a,b;
Rectangle(double a,double b){
this.a=a;
this.b=b;
}
public double getArea() {
return a*b;
}
}
class Pillar{
Gemoetry bottom;
double height;
Pillar(Gemoetry bottom,double height){
this.bottom=bottom;
this.height=height;
}
public double getVolume() {
if(bottom==null) {
System.out.println("底爲空!");
return -1;
} else {
return bottom.getArea()*height;
}
}
}
public class Test1 {
public static void main(String[] args) {
Pillar pillar;
Gemoetry bottom=null;
pillar =new Pillar(bottom,100);
System.out.println("體積"+pillar.getVolume());
bottom=new Rectangle(12,22);//使得bottom成爲Rectangle類的上轉型對象,調用getArea就相當於是Rectangle類在調用
pillar=new Pillar(bottom,58);
System.out.println("體積"+pillar.getVolume());
bottom=new Circle(10);
pillar=new Pillar(bottom,58);
System.out.println("體積"+pillar.getVolume());
}
}
面向抽象編程的目的是爲了應對用戶需求的變化,將某個類中經常因需求變化而需要改動的代碼從該類中分離出去。面型抽象編程的核心是讓類中每種可能的變化對應地交給抽象類的一個子類去負責,從而讓該類的設計者不去關心具體實現,避免所設計的類依賴於具體的實現。面向抽象編程使設計的類容易應對用戶需求的變化。
注:如果進一步學習設計模式,會更深刻地理解面向抽象的重要性,可參見耿翔義老師所作的清華大學出版社出版的《Java設計模式》一書
2.開-閉原則
所謂“開-閉原則”,就是讓設計的系統對擴展開放,對修改關閉。
這句話的本質是指當系統中增加新的模塊時,不需要修改現有的模塊。如果系統的設計遵守了“開-閉原則”,那麼這個系統一定是易於維護的,因爲在系統中增加新的模塊時,不必去修改系統中的核心模塊。
通常我們無法讓設計的每個部分都遵守“開-閉原則”,甚至不應當這樣去做,應當把主要精力用來集中應對設計中最有可能因需求變化而需要改變的地方,然後想辦法應用“開-閉原則”。
3.應用舉例
用類封裝手機的基本屬性和功能,要求手機既可以使用激動公司的SIM卡,也可以使用聯通公司的SIM卡
abstract class SIM{
abstract void showNumber();
abstract void setNumber(String number);
abstract void showCorpName();
}
class SIM1 extends SIM{
String phoneNumber;
void showNumber() {
System.out.println(phoneNumber);
}
void setNumber(String number) {
phoneNumber=number;
}
void showCorpName() {
System.out.println("中國移動");
}
}
class SIM2 extends SIM{
String phoneNumber;
void showNumber() {
System.out.println(phoneNumber);
}
void setNumber(String number) {
phoneNumber=number;
}
void showCorpName() {
System.out.println("中國聯通");
}
}
class MobilePhone{
SIM sim;
void setSIM(SIM sim) {
this.sim=sim;
}
void showMessage() {
System.out.println("電話號碼:");
sim.showNumber();
System.out.println("公司:");
sim.showCorpName();
}
}
public class Test1{
public static void main(String[] args) {
MobilePhone m = new MobilePhone();
SIM s = new SIM1();
s.setNumber("123456");
m.setSIM(s);
m.showMessage();
s=new SIM2();
s.setNumber("654321");
m.setSIM(s);
m.showMessage();
}
}