客户需要某个产品,客户直接和生成该产品的工厂打交道,工厂具体来负责产品的实现
package cn.javass.dp.simplefactory.example4; /** * 某个接口(通用的、抽象的、非具体的功能的) */ public interface Api { /** * 某个具体的功能方法的定义,用test1来演示一下。 * 这里的功能很简单,把传入的s打印输出即可 * @param s 任意想要打印输出的字符串 */ public void test1(String s); }
package cn.javass.dp.simplefactory.example4; /** * 对某个接口的一种实现 */ public class Impl implements Api{ public void test1(String s) { System.out.println("Now In Impl. The input s=="+s); } }
package cn.javass.dp.simplefactory.example4; /** * 对接口的一种实现 */ public class Impl2 implements Api{ public void test1(String s) { System.out.println("Now In Impl2. The input s=="+s); } }
package cn.javass.dp.simplefactory.example4; /** * 工厂类,用来创造Api的 */ public class Factory { /** * 具体的创造Api的方法,根据客户端的参数来创建接口 * @param type 客户端传入的选择创造接口的条件 * @return 创造好的Api对象 */ public static Api createApi(int type){ //这里的type也可以不由外部传入,而是直接读取配置文件来获取 //为了把注意力放在模式本身上,这里就不去写读取配置文件的代码了 //根据type来进行选择,当然这里的1和2应该做成常量 Api api = null; if(type==1){ api = new Impl(); }else if(type==2){ api = new Impl2(); } return api; } }
package cn.javass.dp.simplefactory.example4; /** * 客户端:测试使用Api接口 */ public class Client { public static void main(String[] args) { //重要改变,没有new Impl()了,取而代之Factory.createApi() //注意这里传递的参数,修改参数就可以修改行为,试试看吧 Api api = Factory.createApi(2); api.test1("哈哈,不要紧张,只是个测试而已!"); } }
上面这种存在一定的问题:
就是客户端在调用Api api = Factory.createApi(2);必须知道参数1 2 3的意思,可以采用下面的办法进行解决,我们通过配置文件来解决,这样客户端不需要内部的参数的意思了
我们在src目录下编写一个配置文件
FactoryTest.properties
ImplClass=cn.javass.dp.simplefactory.example5.Impl
package cn.javass.dp.simplefactory.example5; import java.util.*; import java.io.*; /** * 工厂类,用来创造Api对象 */ public class Factory { /** * 具体的创造Api的方法,根据配置文件的参数来创建接口 * @return 创造好的Api对象 */ public static Api createApi(){ //直接读取配置文件来获取需要创建实例的类 //至于如何读取Properties还有如何反射这里就不解释了 Properties p = new Properties(); InputStream in = null; try { in = Factory.class.getResourceAsStream("FactoryTest.properties"); p.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(p.getProperty("ImplClass")).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return api; } }
调用者就是不需要具体参数的意见了
package cn.javass.dp.simplefactory.example5; /** * 客户端:测试使用Api接口 */ public class Client { public static void main(String[] args) { //重要改变,没有new Impl()了,取而代之Factory.createApi() Api api = Factory.createApi(); api.test1("哈哈,不要紧张,只是个测试而已!"); } }
简单工厂的本质是:选择而不是实现,选择的参数可以来自客户端,也可以来自配置文件,通过参数来选择不同类型的实现,实现类的功能不能放在工厂中去实现,实现类应该提前就做好
public static Api createApi(int type){ //这里的type也可以不由外部传入,而是直接读取配置文件来获取 //为了把注意力放在模式本身上,这里就不去写读取配置文件的代码了 //根据type来进行选择,当然这里的1和2应该做成常量 Api api = null; if(type==1){ api = new Impl(); }else if(type==2){ api = new Impl2(); } return api; }
不能把Impl的具体实现放在工厂类中是写,工厂类是依据参数来选择不同的实现类
补充三:
简单工厂的扩充
上面只提供了一个业务类
package cn.javass.dp.simplefactory.example4; /** * 某个接口(通用的、抽象的、非具体的功能的) */ public interface Api { /** * 某个具体的功能方法的定义,用test1来演示一下。 * 这里的功能很简单,把传入的s打印输出即可 * @param s 任意想要打印输出的字符串 */ public void test1(String s); }
如果还存在其他的业务操作,也可以采用下面的简单工厂来实现
时间: 2024-10-22 10:32:08