核心思想:
尽可能地少改代码!
程序的编写就像建房子一样!
(老师给我举的例子,我很喜欢,注意看注释哦~)
第一步:建框架
(这个例子是用来计算不同底面的柱体体积的例子)
interface Geometry //底面积,接口,DIY区域
{
double getArea(); //函数重写即为 DIY
}
class Pillar{
int height=100;
Geometry s;
}
体积=底面积 x 高
第二步:装修并留出我要DIY的区域
class Pillar{
int height=100;
Geometry s;
double getVolume() {
return height*s.getArea();
} //装修就是实现程序计算体积的功能
void setGeometry(Geometry s){
this.s=s;
}//注入接口,完成底面的 DIY
}
第三步:DIY的内容
class Circle implements Geometry{ //圆作底面
double r;
Circle(double[] n){
r=n[0];
}
public double getArea() {
return 3.14*r*r;
}
}
class Rectangle implements Geometry{ //矩形作底面
double x,y;
Rectangle(double[] n){
x=n[0];
y=n[1];
}
public double getArea() {
return x*y;
}
}
第四步:DIY内容 “ 注入 ”
A.setGeometry((Geometry)door);
//由传入的Geometry对象设置底面形状
Ps:
这里我是用配置文件通过反射获取对象
然后上转型成接口~
下面是完整源码:
import java.util.Scanner;
import java.lang.Thread;
import java.util.Vector;
import java.util.regex.Pattern;
import java.io.*;
import java.math.*;
import java.util.*;
import java.lang.reflect.*;
interface Geometry
{
double getArea();
}
class Circle implements Geometry{ //圆作底面
double r;
Circle(double[] n){
r=n[0];
}
public double getArea() {
return 3.14*r*r;
}
}
class Rectangle implements Geometry{ //矩形作底面
double x,y;
Rectangle(double[] n){
x=n[0];
y=n[1];
}
public double getArea() {
return x*y;
}
}
class Pillar{ //柱体
int height=100;
Geometry s;
double getVolume() { //求体积
return height*s.getArea();
}
void setGeometry(Geometry s){ //设置底面
this.s=s;
}
}
public class Main1 {
public static void main(String[] args) {
Pillar A=new Pillar();
Properties pro;
pro=new Properties();
File f=new File("bottom.properties");
if(f.exists()){
try {
pro.load(new FileInputStream(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
String data=pro.getProperty("data");
String []group=data.split(",");
double []Data=new double[group.length];
for(int i=0;i<group.length;i++) {
Data[i]=Double.valueOf(group[i]);
}
Class<?> s=null;
try {
s = Class.forName(pro.getProperty("shape"));
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
Constructor<?> cons=null;
try {
cons = s.getDeclaredConstructor(double[].class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
Object door=null;
try {
door = cons.newInstance(Data);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {k
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
A.setGeometry((Geometry)door);
A.getVolume();
System.out.print(A.getVolume());
}
}
配置文件
文件名:“ bottom.properties ”
内容:
shape=Rectangle
data=1.0,2.0
后话:
以后有新的形状,我要做的只是单纯地加入新的形状类,并在配置文件中修改shape和data的值即可,代码一丁点都不需要改!!——难怪说反射是Java的强力武器。。。
这里啰嗦一些上转型
——接口可以说是父类,既然是父类那就是 “ 包含 ” 了子类
即父类大,那么我们转化时
应该由小的子类转化成大的父类才不会出现错误!
类比,小的short转化成大的int 不会产生误差
但是,大的int转化成short 是可能产生误差的
所以我们一般不把int转成short,而是将short转成int
回到类,我们只允许小的子类转化成大的父类
而不允许大的父类转化成小的子类
这套机制在面向对象编程中也存在
——抽象类 C++也是一样的道理