一、工厂设计
interface Fruit{//定义一个水果的接口
public void eat();//吃水果的方法
}
class Apple implements Fruit{//定义子类 Apple
public void eat(){
System.out.println("** 吃萍果");
}
}
class Orange implements Fruit{//定义子类Orange
public void eat(){//覆写eat()方法
System.out.println("**吃橘子");
}
}
public class Test{
public static void main(String[] args) {
Fruit f = new Apple();//实例化接口
f.eat();//调用方法
}
}
子类为接口实例化后,调用被子类覆写过的方法。
我们已知主方法实际如同一个客户端,如果此时需要更换一个子类,就必须要修改主方法,这就存在问题了。
我们可以在接口和具体子类之间加入一个过渡段,通过过渡段取得接口实例
这个过渡段一般被称为工厂类
class Factory{//定义工厂类
public static Fruit getInstance(String className){
Fruit f = null;//定义接口对象
if("apple".equals(className)){//判断是哪个子类的标记
f = new Apple();//通过 Apple 类实例化接口
}
if("orange".equals(className)){//判断是哪个子类的标记
f = new Apple();//通过 orange 类实例化接口
}
return f;
}
}
public class Test{
public static void main(String[] args) {
Fruit f = null;//定义接口对象
f = Factory.getInstance("apple");//通过工厂取得实例
f.eat();//调用方法
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
此时以后再有子类扩充,可以直接修改工厂类客户端就可以根据标记得到相应的实例,灵活性较高。
同时这里的
if("orange".equals(className))
而不是
if(className.equals("orange"))
- 1
- 2
- 3
这样做可以避免空指向异常,因为这里的className可能为空需要注意
二、代理设计
代理设计也是在 Java 代理主题来操作真实主题,真实主题执行具体的业务操作,而代理主题负责其他相关业务的处理,如同生活中使用的代理上网一样,客户通过网络代理连接网络,由代理服务器完成用户权限和访问限制等与上网操作相关的操作。
interface Network{//定义 Network 接口
public void browse();//定义浏览的抽象方法
}
class Real implements Network{//真实的上网操作
public void browse(){//覆写抽象方法
System.out.println("上网浏览信息");
}
}
class Proxy implements Network{
//代理上网
private Network network;
public Proxy(Network network){
//设置代理的真实操作
this.network = network;//设置代理的子类
}
public void check(){//与具体上网相关的操作
System.out.println("检查用户是否合法");
}
public void browse(){
this.check();//可以同时调用多个与具体业务相关的操作
this.network.browse();//调用真实上网操作
}
}
public class Test{
public static void main(String[] args) {
Network net = null;//定义接口对象
//相当于向上转型,执行的都是子类覆盖后的方法
net = new Proxy(new Real());//实例化代理,同时传入代理的真实操作
net.browse();//客户只关心上网浏览一个功能
}
}
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
三、适配器设计
对于 Java 程序来说,如果一个类要实现一个接口,必须覆写此接口中的全部抽象方法,那么如果此时一个接口中定义的抽象方法过多,但是子类中又用不到这么多抽象方法,肯定很麻烦,此时就需要一个中间的过渡,但是此过渡类又不希望被直接使用,
所以将此过渡类定义成抽象类最合适,即一个接口首先被一个抽象类先实现(此抽象类通常称为适配器),并在此抽象类中实现若干方法(方法体为空),则以后的子类直接继承此抽象类,就可以有选择地覆写所需要的方法。
interface Window{
//定义Window 接口,表示窗口操作
public void open();//窗口打开
public void close();//窗口关闭
public void activated();//窗口活动
public void iconified();//窗口最小化
public void deiconified();//窗口恢复大小
}
//定义抽象类实现接口,在此类中覆写方法,但是所有的方法体为空
//这个抽象类称为适配器
abstract class WindowAdapter implements Window{
public void activated(){};//覆写 activated()方法,方法体为空
public void close(){}
public void deiconified(){}
public void iconified(){}
public void open(){}
}
//子类直接继承 WindowAdapter 类,有选择地实现需要的方法
class WindowImp1 extends WindowAdapter{
public void open(){
//真正实现 open()方法
System.out.println("窗口打开");
}
public void close(){
//真正实现 close() 方法
System.out.println("窗口关闭");
}
}
public class Test{
public static void main(String[] args) {
Window win = new WindowImp1();//实现接口对象
win.open();//调用 open()方法
win.close();//调用 close()方法
}
}
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
由于代码中采用了适配器这个中间环节,所以子类就不用必须实现接口中的全部方法,而是有选择的实现所需要的方法
在以后学习图形界面部分时,会有大量的事件监听接口,如果全部实现方法会相当不方便,所以在Java中提供大量的适配器类来使用