1.1 场景问题
在 Java 应用开发中,经常需要 “面向接口编程”。
1.1.1 接口
接口中的所有方法都是静态方法,所有属性都是常量。
接口的思想:封装隔离
封装:”对被隔离体的行为的封装“ 或者是 “对被隔离体的职责的封装”
隔离:外部调用和内部实现,外部调用只能通过接口进行调用,外部调用时不知道内部具体实现的。
1.1.2 面向接口编程
在 Java 程序设计中,通常按照三层来划分 Java 程序,分别是表现层、逻辑层、数据层。
这三层之间的通信都需要接口来实现,接口是被其隔离部分的外观。
1.1.3 传统的解决方案
Api api = new ApiImpl();
1.1.4 出现的问题
我们知道接口的思想是 封装隔离
,而实现类 ApiImpl 应该是被接口 Api 封装并同客户端隔离开的。也就是说客户端不应该知道接口具体的实现类是 ApiImpl。
1.2.1 使用简单工厂解决问题
-
简单工厂的定义
提供一个创建对象实例的功能,而无需关心其具体实现。别创建实例的类型可以是接口、抽象类,也可以是具体的类。
-
应用简单工厂来解决问题的思路
在模块内部新建一个类,在这个类里面来创建接口,然后把创建好的接口返回给客户端。
1.2.2 简单工厂代码实例
- Api 接口的定义
/**
* 某个接口(通用的、抽象的、非具体的功能)
* @author Yuu
*
*/
public interface Api {
/**
* 某个具体的功能方法的定义,用 test1 演示
* @param s
*/
public void test1(String s);
}
- ImplA 接口的实现类
/**
* 对接口的实现
* @author Yuu
*
*/
public class ImplA implements Api {
public void test1(String s) {
System.out.println("ImplA s==" + s);
}
}
- ImplB 接口的实现类
/**
* 对接口的实现
* @author Yuu
*
*/
public class ImplB implements Api {
public void test1(String s) {
System.out.println("ImplB s==" + s);
}
}
- Factory 工厂类
/**
* 工厂类
* @author Yuu
*
*/
public class Factory {
/**
* 具体创建 Api 对象的方法
* @param condition
* @return
*/
public static Api createApi(int condition) {
Api api = null;
if (condition == 1) {
api = new ImplA();
} else if (condition == 2) {
api = new ImplB();
}
return api;
}
}
- Client 客户端
public class Client {
public static void main(String[] args) {
// 通过简单工厂来获取接口对象
Api api = Factory.createApi(1);
api.test1("正在使用简单工厂~");
}
}
- 控制台输出
ImplA s==正在使用简单工厂~
1.3 Properties 可配置的简单工厂
- Factory.properties 配置文件
ImplClass=com.yyh.simple.factory.scheme.properties.ImplA
- Factory
/**
* 工厂类
* @author Yuu
*
*/
public class Factory {
public static Api createApi() {
// 直接读取配置文件来获取需要创建实例的类
Properties prop = new Properties();
InputStream in = null;
in = Factory.class.getResourceAsStream("Factory.properties");
try {
prop.load(in);
} catch (IOException e) {
System.out.println("装载工厂配置文件出错了~");
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 用反射去创建
Api api = null;
try {
api = (Api)Class.forName(prop.getProperty("ImplClass")).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
e.printStackTrace();
}
return api;
}
}
1.4 简单工厂的特点
优点:
- 帮助封装
- 解耦
缺点:
- 可能增加客户端的复杂度
- 不方便扩展子工厂
1.5 简单工厂的实现
简单工厂的本质就是选择实现。
1.6 何时选用简单工厂
- 想要完全封装隔离具体实现,让外部只能通过接口来操作封装体。
- 想要把对外创建对象的职责集中管理和控制。