一、定义
工厂模式是一种创建型模式。他提供一种常见对象的方式。通过一个公共的接口来提供给使用者,使其获取对象的引用,隐藏了对象的具体创建过程。
二、详细介绍
1、意图
创建一个创建对象的工厂,让使用者来决定去实例化哪一个工厂类,工厂模式使其创建过程延迟到子类中进行。
2、解决问题
主要解决接口适配选择的问题。当不同的条件下使用不同的实现类时。比如画图:当画圆时使用画圆的实现类,画三角形时使用画三角形的实现类。
3、实现方式
让其子类实现工厂接口,返回一个抽象的产品,具体的实现过程在各个实体类的内部实现,然后通过统一的接口调用来实现。
4、优点
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
5、缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
三、Java实现
1、定义一个多个实体对象共有的功能的接口方法
/**
* 1、定义一个
* @Author guodandan
* @Date 2020/1/18 16:48
*/
public interface Shape {
public void draw();
}
2、定义需要实现的实体类,并是实现该接口
/**
* @Author guodandan
* @Date 2020/1/18 16:58
*/
public class Circle implements Shape {
public void draw() {
System.out.println("step into Circle::draw()");
}
}
/**
* @Author guodandan
* @Date 2020/1/18 16:56
*/
public class Rectangle implements Shape {
public void draw() {
System.out.println("step into Rectangle::draw()");
}
}
3、定义工厂类,用来创建相关对象
/**
* @Author guodandan
* @Date 2020/1/18 16:59
*/
public class ShapeFactory {
/**
* 基于类型选择的工厂对象实现
* 缺点: 每增加一个类型,需要修改工厂方法的适配类型
* @param type 类型
* @return 目标类
*/
public static Shape getShapeByType(int type){
switch (type){
case 1:
return new Rectangle();
case 2:
return new Circle();
default:
return new Circle();
}
}
/**
* 通过反射,利用工厂模式实现目标实现类。
* 优点: 每次增加新的实例对象,不需要修改工厂方法,扩展性好
* @param clazz 目标类class
* @return 目标类
*/
public static Shape getShapeByClass(Class<? extends Shape> clazz){
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
3.1、基于类型选择的工厂对象实现
3.1.1、优点
实现简单,利用if或者switch等方式,代码比较好理解。
3.1.2、缺点
每增加一个类型,需要修改工厂方法的适配类型。
3.1.3、代码实现
/**
* 基于类型选择的工厂对象实现
* 缺点: 每增加一个类型,需要修改工厂方法的适配类型
* @param type 类型
* @return 目标类
*/
public static Shape getShapeByType(int type){
switch (type){
case 1:
return new Rectangle();
case 2:
return new Circle();
default:
return new Circle();
}
}
3.2、通过反射来实现目标对象
3.2.1、缺点
技术要求比较高,难理解。
3.2.2、优点
- 每次增加新的实例对象,不需要修改工厂方法,扩展性好。
- 可以利用类加载器,实现工厂对象的动态扩展,实现热加载。
3.2.3、代码实现
/**
* 通过反射,利用工厂模式实现目标实现类。
* 优点: 每次增加新的实例对象,不需要修改工厂方法,扩展性好
* @param clazz 目标类class
* @return 目标类
*/
public static Shape getShapeByClass(Class<? extends Shape> clazz){
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
4、测试。
4.1、测试【基于类型选择的工厂对象实现】
@Test
public void getShapeByType(){
Shape shape_01 = ShapeFactory.getShapeByType(1);
shape_01.draw();
shape_01 = ShapeFactory.getShapeByType(2);
shape_01.draw();
shape_01 = ShapeFactory.getShapeByType(0);
shape_01.draw();
}
4.2、测试【通过反射来实现目标对象】
@Test
public void getShapeByClass(){
Shape shape_01 = ShapeFactory.getShapeByClass(Circle.class);
shape_01.draw();
shape_01 = ShapeFactory.getShapeByClass(Rectangle.class);
shape_01.draw();
}