初次学完抽象类和接口的童鞋,看多了“面向接口编程"字眼,也见多了“面向接口”的好多好处,总会感觉其神秘。然而有些书不给示例,总让我们感觉它的高不可攀,不知其所用。本篇将简单而又完整的介绍2个面向接口编程的例子。
一、简单工程模式
情景1:一个机器类Computer需要具体的输出设备Printer,有较好的两种方式选择:直接在Computer类中组合Printer类; 在2者之间搭个中介OutPut,使Computer组合OutPut,Printer实现OutPut。 那么如何选择哪种方式呢?暂且选第二种,至于为什么,且看代码慢慢分析...
1、机器类Computer
/**************************************************
* a machine 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午01:35:30
***************************************************/
public class Computer {
// associate OutPut
private OutPut out;
public Computer(OutPut out){
this.out = out;
}
// to test, i change the return value
public String keyIn(String msg){
// pay attention to what out use the method
return out.getData(msg);
}
public void print(String msg){
out.out(msg);
}
}
2、接口OutPut:
/**************************************************
* OutPut interface 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午01:36:28
***************************************************/
public interface OutPut {
/**
* in the Computer class, out use getData() and out() method
*
* so what the interface defines method obeies the needs
*/
// the mothed in the interface is "public abstract" defaultly
public abstract String getData(String msg);
// so it's ok for you to ignore the "abstract" keyword
public void out(String msg);
}
3、输出设备Printer:
/**************************************************
* one of the output device. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午01:42:33
***************************************************/
public class Printer implements OutPut{
/**
* override abstract method to be specific.
*/
@Override
public String getData(String msg) {
return msg;
}
@Override
public void out(String msg) {
System.out.println(msg);
}
}
4、生产OutPut具体对象的工厂类OutPutFactory:
/**************************************************
* the output factory 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午01:41:26
***************************************************/
public class OutPutFactory {
// you can't instantiate an interface, however, you can refer to the interface
public OutPut getOutPut(){
return new Printer();
}
}
5、测试类Test:
/**************************************************
* test class. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午02:20:00
***************************************************/
public class Test {
public static void main(String[] args) {
OutPutFactory of = new OutPutFactory();
Computer cp = new Computer(of.getOutPut());
cp.print(cp.keyIn("这就是简单的工厂模型"));
}
}
这种模型降低了程序间的耦合,即降低程序之间的依赖程度。假如机器Computer升级,不需要低级的Printer设备,想换成BetterPrinter设备,那么只要让BetterPrinter实现OutPut接口、另在工程类修改生产的对象名即可,这样即使大数量的机器Computer升级输入设备也只要这么简单的代码即可完成系统升级。 再看第一种情况-- 直接组合Printer,那么如果百来个Computer需要升级Printer,那么就要修改百来份Computer代码。这就是面向接口的好处之一。
二、命令模式
情景2:假如有个方法需要遍历一个数组,但无法确定在遍历数组时如何处理数组元素,需要在调用该方法时具体指定。 本质上说,这个要求就类似在方法里传一个具体的方法操作作为形参。且看代码实现。
1、处理数组类HandleArrays:
/**************************************************
* 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午03:12:15
***************************************************/
public class HandleArrays {
public void handle(int[] target, Command cmd){
cmd.process(target);
}
}
2、命令接口Command:
/**************************************************
* interface command. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午03:09:22
***************************************************/
public interface Command {
// to encapsulate behavior
public void process(int[] target);
}
3、处理方式之-- 打印PrintCommand:
/**************************************************
* handle in printing. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午03:18:59
***************************************************/
public class PrintCommand implements Command {
@Override
public void process(int[] target) {
for(int temp : target){
System.out.println("输出目标数组的元素是:" + temp);
}
}
}
4、处理方式之-- 求和AddCommand:
/**************************************************
* handle in printing. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午03:18:59
***************************************************/
public class PrintCommand implements Command {
@Override
public void process(int[] target) {
for(int temp : target){
System.out.println("输出目标数组的元素是:" + temp);
}
}
}
......还有很多处理方式
5、测试类Test:
/**************************************************
* 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-14 下午03:16:05
***************************************************/
public class Test {
public static void main(String[] args) {
HandleArrays ha = new HandleArrays();
int[] target = {3, -4, 6, 4};
ha.handle(target, new PrintCommand());
System.out.println("-----------------------");
ha.handle(target, new AddCommand());
}
}
代码很简单吧? 如果你没见过类似代码,可以复制到IDE运行并思考其运行过程,相信会让你重新认识接口,有了新的编码风格。个人其实慢慢熟练这些模型,对你以后对解读框架也是有很大的帮助,毕竟“九层之台起于垒土,千里之行始于足下”!希望本篇对你理解“面向接口”有所帮助...
谢谢您的欣赏!