------- android培训、java培训、期待与您交流! ----------
面向接口编程是JAVA编程中的一个非常重要原则! 在JAVA程序的设计中,通常将系统按三层来分,由上至下分别为表现层,逻辑层和数据层,他们之间互不污染,才能最大的松散耦合,其中关键的思想就是面向接口思想。
既然JAVA中,面向接口编程是一个非常重要的原则,那么在实际项目中如何运用接口来做到真正的面向接口编程?我们在初学JAVA的时候还没有涉及到设计模式,那么这时候是如何使用接口的呢?我们通常是有一个接口叫Api,接着又有一个实现类Impl实现这个接口,然后我们直接在客户端创建一个Impl的实例,将其赋给一个Api接口类型的变量,最后,客户端就可以通过这个变量来操作接口的功能了,这个过程可以用以下代码过程来表示:
1、首先定义接口Api
public interface Api {
public String doSomething();
}
2、实现类Impl
public class Impl implements Api {
public String doSomething() {
return "没有使用工场设计模式!";
}
}
3、客户端
public class App {
public static void main(String[] args) {
Api api = new Impl();
String s = api.doSomething();
System.out.println(s);
}
}
当然,刚开始的时候我们就是这么干的,并没有觉得哪里不对,但是随着学习的深入,我们会发现客户端里面有这么一句代码:
Api api = new Api();
我们会发现,在客户端App里面,客户不仅知道了接口,并且还知道了具体的实现类就是Impl,然而面向接口编程的思想告诉我们,Impl应该是被Api给封装起来,起到将实现类和客户端隔离开来的作用,Impl不应该被暴露给客户,客户不应该直接就调用Impl。这样就有个问题了,既然不让我客户端去直接得到Impl,那我从哪里得到?找谁要呢?总得有个人将Impl的实例交给我,我才能干活啊!
解决这样一个只知接口不知实现的问题,我们使用到了简单工厂设计模式,简单工厂的定义如下:提供一个创建对象实例的功能,而无需关心其具体实现,被创建实例的类型可以是接口,抽象类,也可以是具体的类。
在工厂内,工厂是知道具体的实现类的,而对于客户端,它不知道工厂内是如何实现的,也不需要知道,客户只需要向工厂提出他想要的东西,工厂就会按照客户端的需求向客户端提供相应的东西,这个工厂我们可以称之为Factory类,因此,客户端就可以通过Factory来获取需要的接口对象,然后调用接口的方法来实现需要的功能就可以了,而完全不需要关心具体的实现了!简单工厂的模式可以用以下代码过程来表示:
1、Api接口定义如下:
public interface Api {
public String doSomething();
}
2、实现类如下,分为两个实现类ImplA、ImplB:
public class ImplA implements Api {
public String doSomething() {
System.out.println("实现类ImplA");
}
}
public class ImplB implements Api {
public String doSomething() {
System.out.println("实现类ImplB");
}
}
3、下面就来实现简单工厂:
public class Factory {
public static Api getApi(int type) {//简单工厂只是一个工具类,没有创建实例的必要,方法最好使用静态
Api api = null;
if (type == 1) {
api = new ImplA();
} else if (type == 2) {
api = new ImplB();
}
return api;
}
}
4、客户端使用简单工厂,有了工厂,客户端就不需要亲自创建接口对象了,示例如下:
public class App {
public static void main() {
Api api = Factory.getApi(1);
api.doSomething();
}
}
从上面可以看出来,客户端在不知道具体的实现类的情况下获取到了想要的接口Api。JAVA设计模式里面的工厂可以包含很多创建东西的方法,这些方法可以创建不同的接口、抽象类或者是类实例。从这里我们也可以看出,工厂的本质是选择实现,上面的示例中有两种实现,而实际开发中可能有多个厂家的实现,每个厂家又有多种实现,而不仅仅是两种,那到底选择哪一种实现呢?上面的示例中,客户端向工厂提出需求的时候传入了一个整形的参数,代表了客户要选择的实现类型,这样又出现了新的问题,客户每次调用工厂的时候都要传入一个选择的参数,这就要求客户知道每个参数的意义,某种程度上已经向客户暴露了内部的一些实现细节。那么有没有优化的方法?有,那就是采用配置化的简单工厂。最常用的方式就是使用配置文档,每当实现类有什么增删改的时候都不会影响到工厂,只要在配置文档中做适当的修改即可满足不断变化的需求!此时的工厂可以优化成如下示例:
public class Factory {//在实际应用中通常将Factory类私有化
public static void getApi() {
Properties prop = new Properties();
InputStream in = null;
in = Factory.class.getResourceAsStream("api.properties");
prop.load(in);
Api api = null;
// 这里使用反射得到配置文件中国制定的实现类,反射通常使用在框架中,其实设计模式与框架也是息息相关的
api = (Api) Class.forName(prop.getProperty("ApiImplClass")).newInstance();
return api;
}
}
优化之后的工厂使得客户端使用起来就更加便利了:
public class App {
public static void main(String[] args) {
Api api = Factory.getApi();
api.doSomething();
}
}
到此,简单工厂的思想架构已经体现了出来,在实际应用中的很多情况下都会应用到简单工厂的模式,也会进行适当的变形,但是不管如何变形,其本质是不会改变的:选择实现,其目的就是为客户端选择相应的实现,从而使客户端和实现之间进行解耦,当实现有所变动,客户端根本就不需要做任何的改变,就可以实现相同的功能,或者达到功能的改变。 总的来说,使用简单工厂带来的好处就是,客户端根本就不需要知道具体是由谁来实现功能,也不用关心是怎样实现的,面对工厂,客户端需要做的只是向工厂获取它需要的接口对象就行了!
------- android培训、 java培训、期待与您交流! ----------