本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。
一、介绍
从名称上,顾名思义就是创建产品,按类别分为简单工厂模式、工厂方法模式、抽象工厂模式,主要功能都是帮助我们把对象的实例化操作单独抽取出来,优化系统架构,增强系统的扩展性。
下面,我们一起来看看各个模式的使用方式。
二、简单工厂模式
简单工厂模式,对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象。
- 创建一个接口
- public interface Product {
- void operation1();
- void operation2();
- }
- 创建实现接口的实体类
- public class ConcreateProductA implements Product{
- @Override
- public void operation1() {
- System.out.println("产品A,执行任务1");
- }
- @Override
- public void operation2() {
- System.out.println("产品A,执行任务2");
- }
- }
- public class ConcreateProductB implements Product{
- @Override
- public void operation1() {
- System.out.println("产品B,执行任务1");
- }
- @Override
- public void operation2() {
- System.out.println("产品B,执行任务2");
- }
- }
- 创建一个工厂,生成基于给定信息的实体类的对象
- public class SimpleFactory {
- //使用 create 方法获取形状类型的对象
- public Product create(String productType){
- if(productType == null){
- return null;
- }
- if(productType.equalsIgnoreCase("productA")){
- return new ConcreateProductA();
- }
- if(productType.equalsIgnoreCase("productB")){
- return new ConcreateProductB();
- }
- return null;
- }
- }
- 编写客户端测试类,使用该工厂,通过传递类型信息来获取实体类的对象
- public class FactoryPatternDemo {
- public static void main(String[] args) {
- SimpleFactory simpleFactory = new SimpleFactory();
- //获取 productA 的对象
- Product productA = simpleFactory.create("productA");
- //调用 productA 的 operation1、operation2 方法
- productA.operation1();
- productA.operation2();
- //获取 productB 的对象
- Product productB = simpleFactory.create("productB");
- //调用 productB 的 operation1、operation2 方法
- productB.operation1();
- productB.operation2();
- }
- }
- 执行程序,输出结果:
- 产品A,执行任务1
- 产品A,执行任务2
- 产品B,执行任务1
- 产品B,执行任务2
当然,还可以将创建对象方式进行改进,将SimpleFactory类创建对象的方式改成如下方式:
- public class SimpleFactory {
- //反射机制获取实体类
- public <T> T createByClazzName(Class<? extends T> clazz){
- T obj = null;
- try {
- obj = (T) Class.forName(clazz.getName()).newInstance();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- return obj;
- }
- }
这样做的好处是,当有新的产品加入时,不用修改工厂类,在调用的时候,采用如下方式即可获取对象!
- Product product = new SimpleFactory().create("类名.class");
三、工厂方法模式
和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂。
- 创建一个工厂接口
- public interface FactoryProduct {
- Product create();
- }
- 创建实现接口的实体类
- public class ConcreateFactoryA implements FactoryProduct{
- @Override
- public Product create() {
- return new ConcreateProductA();
- }
- }
- public class ConcreateFactoryB implements FactoryProduct{
- @Override
- public Product create() {
- return new ConcreateProductB();
- }
- }
- 编写客户端测试类,使用该工厂,通过传递类型信息来获取实体类的对象
- public class FactoryPatternDemo {
- public static void main(String[] args) {
- //获取 productA 的对象
- Product productA = new ConcreateFactoryA().create();
- //调用 productA 的 operation1、operation2 方法
- productA.operation1();
- productA.operation2();
- //获取 productB 的对象
- Product productA = new ConcreateFactoryB().create();
- //调用 productB 的 operation1、operation2 方法
- productB.operation1();
- productB.operation2();
- }
- }
- 执行程序,输出结果:
- 产品A,执行任务1
- 产品A,执行任务2
- 产品B,执行任务1
- 产品B,执行任务2
四、抽象工厂模式
抽象工厂模式主要是应对产品族概念提出来的。提供一个创建一系列相关或相互依赖的对象。
- 为形状创建一个接口
- public interface Shape {
- void draw();
- }
- 创建实现接口的实体类
- public class Rectangle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Rectangle::draw() method.");
- }
- }
- public class Square implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Square::draw() method.");
- }
- }
- public class Circle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Circle::draw() method.");
- }
- }
- 为颜色创建一个接口
- public interface Color {
- void fill();
- }
- 创建实现接口的实体类
- public class Red implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Red::fill() method.");
- }
- }
- public class Green implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Green::fill() method.");
- }
- }
- public class Blue implements Color {
- @Override
- public void fill() {
- System.out.println("Inside Blue::fill() method.");
- }
- }
- 为 Color 和 Shape 对象创建抽象类来获取工厂
- public abstract class AbstractFactory {
- public abstract Color getColor(String color);
- public abstract Shape getShape(String shape) ;
- }
- 创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象
- public class ShapeFactory extends AbstractFactory {
- @Override
- public Shape getShape(String shapeType){
- if(shapeType == null){
- return null;
- }
- if(shapeType.equalsIgnoreCase("CIRCLE")){
- return new Circle();
- } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
- return new Rectangle();
- } else if(shapeType.equalsIgnoreCase("SQUARE")){
- return new Square();
- }
- return null;
- }
- @Override
- public Color getColor(String color) {
- return null;
- }
- }
- public class ColorFactory extends AbstractFactory {
- @Override
- public Shape getShape(String shapeType){
- return null;
- }
- @Override
- public Color getColor(String color) {
- if(color == null){
- return null;
- }
- if(color.equalsIgnoreCase("RED")){
- return new Red();
- } else if(color.equalsIgnoreCase("GREEN")){
- return new Green();
- } else if(color.equalsIgnoreCase("BLUE")){
- return new Blue();
- }
- return null;
- }
- }
- 创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂
- public class FactoryProducer {
- public static AbstractFactory getFactory(String choice){
- if(choice.equalsIgnoreCase("SHAPE")){
- return new ShapeFactory();
- } else if(choice.equalsIgnoreCase("COLOR")){
- return new ColorFactory();
- }
- return null;
- }
- }
- 使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象
- public class AbstractFactoryPatternDemo {
- public static void main(String[] args) {
- //获取形状工厂
- AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
- //获取形状为 Circle 的对象
- Shape shape1 = shapeFactory.getShape("CIRCLE");
- //调用 Circle 的 draw 方法
- shape1.draw();
- //获取形状为 Rectangle 的对象
- Shape shape2 = shapeFactory.getShape("RECTANGLE");
- //调用 Rectangle 的 draw 方法
- shape2.draw();
- //获取形状为 Square 的对象
- Shape shape3 = shapeFactory.getShape("SQUARE");
- //调用 Square 的 draw 方法
- shape3.draw();
- //获取颜色工厂
- AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
- //获取颜色为 Red 的对象
- Color color1 = colorFactory.getColor("RED");
- //调用 Red 的 fill 方法
- color1.fill();
- //获取颜色为 Green 的对象
- Color color2 = colorFactory.getColor("Green");
- //调用 Green 的 fill 方法
- color2.fill();
- //获取颜色为 Blue 的对象
- Color color3 = colorFactory.getColor("BLUE");
- //调用 Blue 的 fill 方法
- color3.fill();
- }
- }
- 执行程序,输出结果:
- Inside Circle::draw() method.
- Inside Rectangle::draw() method.
- Inside Square::draw() method.
- Inside Red::fill() method.
- Inside Green::fill() method.
- Inside Blue::fill() method.
五、应用
工厂模式在实际开发中使用非常频繁,例如 JDK 中的日历操作,在国际化的时候,获取本地语言就用到简单工厂模式。
写一个获取测试,如下:
- public static void main(String[] args) {
- //获取日历操作类
- Calendar calendar = Calendar.getInstance();
- int year = calendar.get(Calendar.YEAR);
- // 取月份要加1
- int month = calendar.get(Calendar.MONTH) + 1;
- int day = calendar.get(Calendar.DAY_OF_MONTH);
- int hour = calendar.get(Calendar.HOUR_OF_DAY);
- int minute = calendar.get(Calendar.MINUTE);
- int seconds = calendar.get(Calendar.SECOND);
- // 1-7分别代表 -- 星期日,星期一,星期二,星期三,星期四,星期五,星期六
- int week = calendar.get(calendar.DAY_OF_WEEK);
- // 年-月-日
- System.out.println("year = " + year);
- System.out.println("month = " + month);
- System.out.println("day = " + day);
- //时-分-秒
- System.out.println("hour = " + hour);
- System.out.println("minute = " + minute);
- System.out.println("seconds = " + seconds);
- // 星期
- System.out.println("week = " + week);
- }
进入getInstance()方法,在获取日历类型的时候,内容如下:
六、小结
工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。
但要明确的,工厂模式的接口只会返回一种类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。
上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可!
七、参考
1、菜鸟教程 - 工厂模式
2、博客园 - alpha_panda - 设计模式之工厂模式