定义
提供一个创建对象实例的功能,无须关心具体实现。(被创建类型,接口,抽象类,具体类)。结构和说明
- api 定义客户所需要的功能接口。
- apia,apib 具体实现api的实现类,可能有多个。
- factory :工厂选择适合的类来创建api接口对象。
- client 客户端,通过factory获取api接口对象,然后面向api接口编程。
面向接口编程
接口的思想-“封装隔离”
封装:功能封装在接口内部。隔离:客户端和功能实现隔离开来。面向接口编程的好处:接口不变,内部实现变化不影响外部应用,使得系统更加灵活,易于扩展。
思考:factory 选择接口实现类?如何选?传递参数?如何传递参数?
方式一:参数源于客户端;方式二:参数源于配置文件;方式三:源于系统本身,系统运行时的某个值。
public interface Api{
void callApi();
}
public class ApiA implements Api{
@override
public void callApi(){
System.out.println("call apia...");
}
}
public class ApiB implements Api{
@override
public void callApi(){
System.out.println("call apib...");
}
}
方式一:通过client端传递参数
/*
* 方式一:通过客户端传递choose参数选择具体接口实现类
*/
public class SimpleApiFactory{
private SimpleApiFactory{};
//choose通过client传递参数表明使用那个api
public static Api createApi(int choose){
if (choose == 0) return new APIA();
else if(choose == 1)return new APIB();
else return null;
}
}
public class Client{
public void static main(String []args){
//factory 传递参数表明使用哪个api?(存在隐藏问题)
Api api = SimpleApiFactory.createApi(0);
if (api == null) return;
api.callApi();
}
}
方式二:通过配置文件解析 添加test.properties配置文件,添加ImplClass = ApiB 来指定使用接口实现类。
public class Factory{
private Factory{};
public static Api createApi(){
Properties pro = new Properties();
InputStream in = null;
try{
in = Factory.class.getResourceAsStream("test.properties");
p.load(in);
Api api = null;
api = (Api)Class.forName(p.getProperty("ImplClass")).newInstance();
return api;
}catch(Exception ex){
ex.printStack();
}
finally{
in.close();
}
}
}
方式三:系统运行时的某个系统值
public class Factory{
//系统保存值
public static int count = 0;
private Factory{};
public static Api createApi(){
Api api = null;
if (count<3) {
api = new ApiA();
count++;
}
else if (count>3){
api = new ApiB();
count++;
}
return null;
}
}
简单工厂优缺点
a.帮助模块封装
b.解耦
c.增加客户端的复杂度(需要客户端传递参数,暴露参数定义意义)
d.不方便扩展子工厂简单工厂本质
选择实现何时选用简单工厂
a. 如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选择简单工厂,让客户端通过工厂来获取相应接口,,无须关心具体实现。
b. 如果想把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。