接口体现的是一种规范和实现分离的设计哲学,充分利用接口可以极好地降低程序各模块之间的耦合性,从而提高系统的可扩展性和可维护性。
下面我们来介绍Java面向接口编程之简单工厂模式
有一个场景:假设程序中有个computer类需要组合一个输出设备。
computer类:需要初始化一个输出设备,把需要打印的东西传递到输出设备,输出要打印的东西。
package fang;
public class Computer {
private Output out;
public Computer (Output out) {
this.out= out;
}
public void keyIn(String msg) {
out.getData(msg);
}
public void print() {
out.out();
}
}
Output接口:连接computer类和输出设备(如打印机等等)的接口。computer通过Output接口传入要打印的东西(getData())和输出要打印的东西(out())。
package fang;
public interface Output {
int MAX_CACHE_LINE = 50;
void out();
void getData(String msg);
// default void print(String ... msgs) {
// for(String msg: msgs) {
// System.out.println(msg);
// }
// }
// default void test() {
// System.out.println("the default test");
// }
// //This static method of interface Output can only be accessed as Output.staticTest
// static String staticTest() {
// System.out.println("static staticTest in interFace");
// return "static staticTest in interFace";
// }
// private void foo() {
// System.out.println("private foo");
// }
// private static void bar() {
// System.out.println("bar private static");
// }
}
OutputFactory类:(先看代码,我们再分析)
package fang;
public class OutputFactory {
public Output getOutput() {
return new Printer();
}
public static void main(String[] args) {
OutputFactory of = new OutputFactory();
Computer c = new Computer(of.getOutput());
c.keyIn("高等数学");
c.keyIn("概率论与数理统计");
c.print();
}
}
它其实重要的代码就是getOutput()这个函数,因为它返回的是一个打印设备的实例。
如果我们想给computer类加上的是Printer(),那么getOutput()返回的就是Printer;
如果我们想给computer类加上的是BetterPrinter(),那么getOutput()返回的就是BetterPrinter。
Printer类:
package fang;
interface Product{
int getProductTime();
}
public class Printer implements Output,Product{
private String[] printData = new String [MAX_CACHE_LINE];
private int dataNum=0;
public void out() {
while(dataNum>0) {
System.out.println("打印机打印作业: "+printData[0]);
System.arraycopy(printData, 1, printData, 0, --dataNum);
}
}
public void getData(String msg) {
if(dataNum>= MAX_CACHE_LINE) {
System.out.println("输出队列已满,添加失败");
}
else {
printData[dataNum++]= msg;
//System.out.println(dataNum);
}
}
public int getProductTime() {
return 45;
}
// public static void main(String []args)
// {
// Output o = new Printer();
// o.getData("大学数学");
// o.getData("大学物理");
// o.out();
// Output.staticTest();
// o.getData("概率论与数理统计");
// o.getData("复变函数");
// o.out();
// o.print("孙悟空","猪八戒","唐僧");
// o.test();
// Product p= new Printer();
// System.out.println(p.getProductTime());
// Object obj = p;
// }
}
BetterPrinter类:
package fang;
public class BetterPrinter implements Output {
private String[] printData = new String [MAX_CACHE_LINE*2];
private int dataNum=0;
public void out() {
while(dataNum>0) {
System.out.println("高速打印机正在打印: "+printData[0]);
System.arraycopy(printData, 1, printData, 0, --dataNum);
}
}
public void getData(String msg) {
if(dataNum>= MAX_CACHE_LINE*2) {
System.out.println("输出队列已满,添加失败");
}
else {
printData[dataNum++]= msg;
//System.out.println(dataNum);
}
}
}
运行结果:
情况一:OutputFactory输出的是Printer设备,打印结果见下:
打印机打印作业: 高等数学
打印机打印作业: 概率论与数理统计
情况二:OutputFactory输出的是BetterPrinter设备,打印结果见下:
高速打印机正在打印: 高等数学
高速打印机正在打印: 概率论与数理统计
通过这种方式,即可把所有生成Output对象的逻辑集中在OutputFactory工厂类中管理,而所有需要使用Output对象的类,只需要与Output接口耦合,而不是与其具体的实现类耦合。即使系统中有很多类使用了Printer对象,只要OutputFactory类的getOutput()方法生成的Output对象是BetterPrinter对象,则它们全部都会改为使用BetterPrinter对象,而所有程序无需修改,只需要修改OutputFactory工厂类的getOutput()方法实现即可。