简单工厂模式不能说是一个设计模式,说它是一种编程习惯可能更恰当些。因为它至少不是23种设计模式之一。但它在实际的编程中经常被用到,而且思想也非常简单,可以说是工厂方法模式的一个引导。
简单工厂就是把创建逻辑封装起来,通过type或者 类类型 区分创建不同的实例返回给客户端。
模式结构
简单工厂模式包含如下角色:
Factory:工厂角色
Product:抽象产品角色
ConcreteProduct:具体产品角色
工厂角色:工厂角色负责根据参数不同,创建不同的实例对象。
抽象产品角色:负责申明所有具体实现的通用接口,例如 Course接口,定义方法,study(String type)
具体产品角色:继承抽象产品角色, 工厂角色产出物为具体产品角色的某一个具体对象,具体产品对象一般为多个;
下面给一个demo实例
正常情况下,我们创建一个
提供抽象产品,创建Source接口,接口提供study接口
package com.dsx.design.simpledesign; public interface Source { public void study(); }
编写具体产品角色,编写JavaSource,EnglishSource,都继承自Source接口,对study方法实现。
package com.dsx.design.simpledesign; public class EnglishSource implements Source { public void study() { System.out.println("学习Enlish source"); } }
package com.dsx.design.simpledesign; public class JavaSource implements Source { public void study() { System.out.println("学习java课程"); } }
最后我们提供工厂角色,负责生产具体实例 。
package com.dsx.design.simpledesign; public abstract class SourceFactory { public static Source getSource(String type){ if("java".equalsIgnoreCase(type)){ return new JavaSource(); }else if("Enhlish".equalsIgnoreCase(type)){ return new EnglishSource(); } return null ; } }
然后编写单元测试,测试
package com.dsx.design.simpledesign; public class Test { public static void main(String[] args) { Source source = SourceFactory.getSource("java"); source.study(); } }
这个时候我们就可以根据不同的type生产不同的Source实例,但是如果我们需要添加具体实现的话,就需要修改SourceFactory的代码,添加if判断,这个并不符合开闭原则(对修改关闭,对扩展放开)
所以我们优化上面Factory代码为:
public static Source getSource(Class cls){ Source source = null ; try { try { source = (Source) Class.forName(cls.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } return source ; }
修改单元测试为:
public static void main(String[] args) { Source source = SourceFactory.getSource(JavaSource.class); source.study(); }
上面优化后的代码通过反射实现, 当需要添加具体实现时并不需要修改工厂方法。