工厂方法模式
工厂方法模式一种类模式,也是创建型模式。它是最常用的设计模式。相关代码已同步github在了解工厂方法模式之前,我们先看下工厂方法模式场景现需要设计一个程序(Client)来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取(ImageReader),如GIF图片读取器(GifReader)用于读取GIF格式的图片、JPG图片读取器(JpgReader)用于读取JPG格式的...
工厂方法模式一种类模式,也是创建型模式。它是最常用的设计模式。相关代码已同步github
在了解工厂方法模式之前,我们先看下工厂方法模式
场景
现需要设计一个程序(Client)来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取(ImageReader),如GIF图片读取器(GifReader)用于读取GIF格式的图片、JPG图片读取器(JpgReader)用于读取JPG格式的图片。
(括号中为工厂方法模式的提示:图片读取器对象通过图片读取器工厂ImageReaderFactory来创建,ImageReaderFactory是一个抽象类,用于定义创建图片读取器的工厂方法,其子类GifReaderFactory和JpgReaderFactory用于创建具体的图片读取器对象)
简单工厂模式
所谓工厂,就是一个加工的场所,为了修改时不同动用原始代码,即更好地满足“开闭原则”。
其实如果初学者在看资料时会很疑惑,为什么23中设计模式中没有简单工厂模式,但是它却十分常见的?
- 因为简单工厂模式和工厂方法模式其实是同气连枝的,当工厂方法模式只有一个工厂时,就会抽象为简单工厂模式
- 如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”
一共包含四个角色:
- 工厂:加工使用产品
- 产品接口
- 具体产品实现类
- 客户端
类图
实例
-
当我们不采用任何设计模式完成上述场景问题时:
// 当增加新功能的时候,需要直接修改产品 public class ImageReader{ public static void imageReader(String type){ if(type.equals("GIF")){ System.out.println("GIF"); } else if(type.equals("Jpg")){ System.out.println("Jpg"); } } } public class Client{ public static void main(String[] args){ ImageReader.imageReader("GIF"); // "Jpg" } }
我们可以发现,这严重的违反了开闭原则,当我们需要对程序进行扩展的时候,需要我们修改ImageReader,即源文件!
-
当我们采用简单工厂模式的时候:
产品
当增加新功能的时候,不用对产品进行修改,只用扩展就行,符合开闭原则
interface ImageReader{ void imageReader(); } public class GifReader{ @Override public void imageReader(){ System.out.println("GIF"); } } public class JpgReader{ @Override public void imageReader(){ System.out.println("JPG"); } }
工厂
如果增加新功能的话还是需要修改此处
public class ImageReaderFactory{ public static void getImageReader(String type){ if(type.equals("GIF")){ return new GifReader(); } else if(type.equals("Jpg")){ return new JpgReader(); } } }
客户端
public class Client{ public static void main(String[] args){ // 此处也可以把gif写到xml中 ImageReaderFactory.getImageReader("GIF").imageReader(); // "Jpg" } }
其实,Java源码中的java.text.DateFormate
某种程度上也起到了工厂的功能,从它的一些方法中:
public static final DateFormat getDateInstance();
public static final DateFormat getDateInstance(int style);
public static final DateFormat getDateInstance(int style, Locale aLocale);
client会调用这些方法获取实例,这些方法就可以看成一个“简单工厂”
利弊
从上面的例子我们可以看出:
- 工厂类含有必要的判断逻辑,即使配置XML也需要
- 通过产品和工厂实现了对责任的分割,符合单一职责原则
- 工厂类中集中了所有产品的创建逻辑,工厂类不够灵活,一旦工厂出错,整个程序将瘫痪
工厂方法
- 工厂方法是为了解决简单工厂模式而诞生的
- 更好地利用了面向对象的多态,将工厂抽象,使得不用修改工厂就可以轻松扩展程序
- 比简单工厂模式更符合开闭原则
一共包含五个角色:
- 产品接口
- 实际产品
- 工厂接口
- 实际生成产品的工厂
- 客户端
类图
实例
我们根据博客开篇的场景说一下工厂方法模型:
产品
当新增产品需求时,产品代码不用改变,只需新增加一个产品类实现产品接口即可
public interface ImageReader {
void imageReader();
}
public class JpgReader implements ImageReader{
@Override
public void imageReader() {
System.out.println("Jpg reader is init");
}
}
public class GifReader implements ImageReader {
@Override
public void imageReader() {
System.out.println("Gif reader is init");
}
}
工厂
当新增产品需求时,产品代码不用改变,只需新增加一个工厂类即可
public interface ImageReaderFactory {
ImageReader getImageReader();
}
public class GifReaderFactory implements ImageReaderFactory{
@Override
public ImageReader getImageReader() {
return new GifReader();
}
}
public class JpgReaderFactory implements ImageReaderFactory{
@Override
public ImageReader getImageReader() {
return new JpgReader();
}
}
客户端
public class Client {
private final static String FACTORY_METHOD = "factoryMethod";
public static void runFactory() {
String packageName = ImageReaderFactory.class.getPackageName();
// 下面是一个XML文件读取的方法,我Github中有写,这里不赘述。
// 当新增产品时,只需增加相应的实现类,修改XML中的配置文件即可,完全不用修改源代码
ImageReaderFactory imageReaderFactory = (ImageReaderFactory)ReadXml.getObject(packageName, FACTORY_METHOD);
if (imageReaderFactory == null){
System.out.println("xml 配置错误");
} else {
imageReaderFactory.getImageReader().imageReader();
}
}
}
应用
-
Spring IOC 控制反转即用的工厂模式
-
Mybatis 中的
SqlSessionFactory
-
java.util.Collection.iterator()
对于iterator来说:
Collection.iterator
即是一个抽象工厂方法,而List.iterator
等子类的该方法则是具体实现方法
而抽象的产品则是Iterator
这个接口,具体的产品则是List等子类中的内部类Itr
,查看源码可知,Itr实现了Iterator这个接口。
同时,具体工厂也调用了Itr这个内部产品类
总结
- 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名
- 工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。基于工厂角色和产品角色的多态性设计是工厂方法模式的关键
- 完美符合开闭原则
- 工厂方法可以退化为简单工厂模式
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)