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();
}
}