浅谈设计模式之简单工厂模式
设计模式:是指在软件开发中,经过验证的,用于解决在特定环境下、重复出现的、特定问题的解决方案。
简单工厂是一个简单而又神奇的设计模式,接下来我们进入正题。
面向接口编程是java编程中的一个重要原则,在java程序设计里面,非常讲究层的划分和模块的划分。通常按照三层来划分java程序,分别是表现层、逻辑层和数据层,他们之间都要通过接口来通信。在每一层里,又有很多的小模块,每一个模块对外则是一个整体,所以每一个模块对外都应该提供接口。其他地方需要使用此模块时,则调用这个模块的接口即可。
通过组件封装的面向接口编程:
首先定义接口
package com.itheima;
/**
* @author hezhiyu
* 定义接口:用于约束实现类的行为,相当于一份合同,约定了实现类应该要实现的功能
*/
public interface Api {
public void operation(String str);
}
实现类:
package com.itheima;
/**
* @author hezhiyu
*/
public class ImplA implements Api{
/* (non-Javadoc)
* @see com.itheima.Api#test(java.lang.String)
* 对接口的实现
*/
@Override
public void operation(String str) {
System.out.println("ImplA:" + str);
}
}
不同的实现类:
package com.itheima;
/**
* @author hezhiyu
*/
public class ImplB implements Api{
/* (non-Javadoc)
* @see com.itheima.Api#test(java.lang.String)
* 对接口的实现
*/
@Override
public void operation(Stringstr) {
System.out.println("ImplB:" + str);
}
}
客户端,按照java接口知识,接口是不能直接使用的,需要使用接口的实现类:
package com.itheima;
/**
* @author hezhiyu
* 客户端测试
*/
public class Client {
public staticvoid main(String[] args) {
Apiapia = new ImplA();
Apiapib = new ImplB();
apia.operation("林青霞来也");
apib.operation("徐霞客来也");
}
}
此时,弊端就体现出来了,客户端不但知道了接口,还知道了接口的实现类。接口的思想是“封装隔离”,也就是说客户端根本就不应该知道接口的实现类。
只知接口而不知实现,该怎么做呢?
简单工厂的定义:
提供一个创建对象实例的功能,而无需关心其具体的实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
使用简单工厂
package com.itheima;
/**
* @author hezhiyu
*/
public class Factory {
/**
* 创建具体Api对象
* @param type 客户端传入的选择创建接口的条件
* @return Api
*/
public static Api createApi(inttype){
/*
* 选择究竟哪一个具体的实现
*/
Apiapi = null;
if(type == 1){
api = new ImplA();
}elseif(type == 2){
api = new ImplB();
}
return api;
}
}
客户端没什么变化,只是在调用Factory的createApi方法时需要传入参数:
package com.itheima;
/**
* @author hezhiyu
* 客户端测试
*/
public class Client {
public staticvoid main(String[] args) {
Apiapi = Factory.createApi(1);
api.operation("正在使用简单工厂");
}
}
这种方法有一个缺点,就是从客户端在调用工厂模式的时候传入选择的参数,这就说明客户端必须知道每个参数的含义.这就向客户暴露一定的内部实现细节.
每次新增加一个实现类都来修改工厂类的实现,肯定不是一个好的实现方式.一个好的解决方法就是使用配置文件.当然也可以使用IoC/DI来实现,这个不在这里讨论.
package com.itheima;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author hezhiyu
*
*/
public class FactoryProperties {
public static Api createApi(){
//直接读取配置文件来获取需要创建实例的类,至于如何读取配置的,如何使用反射这里就不做解释了
Propertiesp = new Properties();
InputStreamin =null;
in = FactoryProperties.class.getResourceAsStream("Factory.properties");
try {
p.load(in);
}catch (IOException e) {
System.out.println("装载工厂配置文件错误:");
e.printStackTrace();
}finally {
try {
in.close();
}catch (IOException e) {
e.printStackTrace();
}
}
Apiapi = null;
try {
api = (Api) Class.forName(p.getProperty("Impl")).newInstance();
}catch (InstantiationException e) {
e.printStackTrace();
}catch (IllegalAccessException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
returnapi;
}
}
客户端测试:这样就不用写参数了
package com.itheima;
/**
* @author hezhiyu
* 客户端测试
*/
public class Client {
public staticvoid main(String[] args) {
Apiapi = FactoryProperties.createApi();
api.operation("正在使用可配置的简单工厂");
}
}
总结:
简单工厂有以下优点:
帮助封装
简单工厂虽然简单,但是非常友好地帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程
解耦
实现了客户端和具体实现类的解耦