初次学完抽象类和接口的童鞋,看多了“面向接口编程"字眼,也见多了“面向接口”的好多好处,总会感觉其神秘。然而有些书不给示例,总让我们感觉它的高不可攀,不知其所用。本篇将简单而又完整的介绍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运行并思考其运行过程,相信会让你重新认识接口,有了新的编码风格。个人其实慢慢熟练这些模型,对你以后对解读框架也是有很大的帮助,毕竟“九层之台起于垒土,千里之行始于足下”!希望本篇对你理解“面向接口”有所帮助...
谢谢您的欣赏!