工厂设计模式案例详解,不服来辩!

开发 前端
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。

[[415212]]

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,今天我们一起来彻底解析一下它。

一、介绍

从名称上,顾名思义就是创建产品,按类别分为简单工厂模式、工厂方法模式、抽象工厂模式,主要功能都是帮助我们把对象的实例化操作单独抽取出来,优化系统架构,增强系统的扩展性。

下面,我们一起来看看各个模式的使用方式。

二、简单工厂模式

简单工厂模式,对象创建管理方式最为简单,因为其仅仅简单的对不同类对象的创建进行了一层薄薄的封装。该模式通过向工厂传递类型来指定要创建的对象。

  • 创建一个接口
  1. public interface Product { 
  2.    void operation1(); 
  3.    void operation2(); 
  • 创建实现接口的实体类
  1. public class ConcreateProductA implements Product{ 
  2.  
  3.    @Override 
  4.    public void operation1() { 
  5.       System.out.println("产品A,执行任务1"); 
  6.    } 
  7.     
  8.    @Override 
  9.    public void operation2() { 
  10.       System.out.println("产品A,执行任务2"); 
  11.    } 
  1. public class ConcreateProductB implements Product{ 
  2.  
  3.    @Override 
  4.    public void operation1() { 
  5.       System.out.println("产品B,执行任务1"); 
  6.    } 
  7.     
  8.    @Override 
  9.    public void operation2() { 
  10.       System.out.println("产品B,执行任务2"); 
  11.    } 
  • 创建一个工厂,生成基于给定信息的实体类的对象
  1. public class SimpleFactory { 
  2.      
  3.    //使用 create 方法获取形状类型的对象 
  4.    public Product create(String productType){ 
  5.       if(productType == null){ 
  6.          return null
  7.       } 
  8.       if(productType.equalsIgnoreCase("productA")){ 
  9.          return new ConcreateProductA(); 
  10.       } 
  11.       if(productType.equalsIgnoreCase("productB")){ 
  12.          return new ConcreateProductB(); 
  13.       } 
  14.       return null
  15.    } 
  • 编写客户端测试类,使用该工厂,通过传递类型信息来获取实体类的对象
  1. public class FactoryPatternDemo { 
  2.   
  3.    public static void main(String[] args) { 
  4.       SimpleFactory simpleFactory = new SimpleFactory(); 
  5.        
  6.       //获取 productA 的对象 
  7.       Product productA = simpleFactory.create("productA"); 
  8.   
  9.       //调用 productA 的 operation1、operation2 方法 
  10.       productA.operation1(); 
  11.       productA.operation2(); 
  12.   
  13.       //获取 productB 的对象 
  14.       Product productB = simpleFactory.create("productB"); 
  15.   
  16.       //调用 productB 的 operation1、operation2 方法 
  17.       productB.operation1(); 
  18.       productB.operation2(); 
  19.    } 
  • 执行程序,输出结果:
  1. 产品A,执行任务1 
  2. 产品A,执行任务2 
  3. 产品B,执行任务1 
  4. 产品B,执行任务2 

当然,还可以将创建对象方式进行改进,将SimpleFactory类创建对象的方式改成如下方式:

  1. public class SimpleFactory { 
  2.      
  3.    //反射机制获取实体类 
  4.    public <T> T createByClazzName(Class<? extends T> clazz){ 
  5.   T obj = null
  6.   try { 
  7.    obj = (T) Class.forName(clazz.getName()).newInstance(); 
  8.   } catch (Exception e) { 
  9.    // TODO Auto-generated catch block 
  10.    e.printStackTrace(); 
  11.   } 
  12.   return obj; 
  13.  } 

这样做的好处是,当有新的产品加入时,不用修改工厂类,在调用的时候,采用如下方式即可获取对象!

  1. Product product = new SimpleFactory().create("类名.class"); 

三、工厂方法模式

和简单工厂模式中工厂负责生产所有产品相比,工厂方法模式将生成具体产品的任务分发给具体的产品工厂。

  • 创建一个工厂接口
  1. public interface FactoryProduct { 
  2.    Product create(); 
  • 创建实现接口的实体类
  1. public class ConcreateFactoryA implements FactoryProduct{ 
  2.  
  3.    @Override 
  4.    public Product create() { 
  5.       return new ConcreateProductA(); 
  6.    } 
  1. public class ConcreateFactoryB implements FactoryProduct{ 
  2.  
  3.    @Override 
  4.    public Product create() { 
  5.       return new ConcreateProductB(); 
  6.    } 
  • 编写客户端测试类,使用该工厂,通过传递类型信息来获取实体类的对象
  1. public class FactoryPatternDemo { 
  2.  
  3.    public static void main(String[] args) { 
  4.  
  5.       //获取 productA 的对象 
  6.       Product productA = new ConcreateFactoryA().create(); 
  7.  
  8.       //调用 productA 的 operation1、operation2 方法 
  9.       productA.operation1(); 
  10.       productA.operation2(); 
  11.  
  12.       //获取 productB 的对象 
  13.       Product productA = new ConcreateFactoryB().create(); 
  14.  
  15.       //调用 productB 的 operation1、operation2 方法 
  16.       productB.operation1(); 
  17.       productB.operation2(); 
  18.    } 
  • 执行程序,输出结果:
  1. 产品A,执行任务1 
  2. 产品A,执行任务2 
  3. 产品B,执行任务1 
  4. 产品B,执行任务2 

四、抽象工厂模式

抽象工厂模式主要是应对产品族概念提出来的。提供一个创建一系列相关或相互依赖的对象。

  • 为形状创建一个接口
  1. public interface Shape { 
  2.    void draw(); 
  • 创建实现接口的实体类
  1. public class Rectangle implements Shape { 
  2.   
  3.    @Override 
  4.    public void draw() { 
  5.       System.out.println("Inside Rectangle::draw() method."); 
  6.    } 
  1. public class Square implements Shape { 
  2.   
  3.    @Override 
  4.    public void draw() { 
  5.       System.out.println("Inside Square::draw() method."); 
  6.    } 
  1. public class Circle implements Shape { 
  2.   
  3.    @Override 
  4.    public void draw() { 
  5.       System.out.println("Inside Circle::draw() method."); 
  6.    } 
  • 为颜色创建一个接口
  1. public interface Color { 
  2.    void fill(); 
  • 创建实现接口的实体类
  1. public class Red implements Color { 
  2.   
  3.    @Override 
  4.    public void fill() { 
  5.       System.out.println("Inside Red::fill() method."); 
  6.    } 
  1. public class Green implements Color { 
  2.   
  3.    @Override 
  4.    public void fill() { 
  5.       System.out.println("Inside Green::fill() method."); 
  6.    } 
  1. public class Blue implements Color { 
  2.   
  3.    @Override 
  4.    public void fill() { 
  5.       System.out.println("Inside Blue::fill() method."); 
  6.    } 
  • 为 Color 和 Shape 对象创建抽象类来获取工厂
  1. public abstract class AbstractFactory { 
  2.    public abstract Color getColor(String color); 
  3.    public abstract Shape getShape(String shape) ; 
  • 创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象
  1. public class ShapeFactory extends AbstractFactory { 
  2.      
  3.    @Override 
  4.    public Shape getShape(String shapeType){ 
  5.       if(shapeType == null){ 
  6.          return null
  7.       }         
  8.       if(shapeType.equalsIgnoreCase("CIRCLE")){ 
  9.          return new Circle(); 
  10.       } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ 
  11.          return new Rectangle(); 
  12.       } else if(shapeType.equalsIgnoreCase("SQUARE")){ 
  13.          return new Square(); 
  14.       } 
  15.       return null
  16.    } 
  17.     
  18.    @Override 
  19.    public Color getColor(String color) { 
  20.       return null
  21.    } 
  1. public class ColorFactory extends AbstractFactory { 
  2.      
  3.    @Override 
  4.    public Shape getShape(String shapeType){ 
  5.       return null
  6.    } 
  7.     
  8.    @Override 
  9.    public Color getColor(String color) { 
  10.       if(color == null){ 
  11.          return null
  12.       }         
  13.       if(color.equalsIgnoreCase("RED")){ 
  14.          return new Red(); 
  15.       } else if(color.equalsIgnoreCase("GREEN")){ 
  16.          return new Green(); 
  17.       } else if(color.equalsIgnoreCase("BLUE")){ 
  18.          return new Blue(); 
  19.       } 
  20.       return null
  21.    } 
  • 创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂
  1. public class FactoryProducer { 
  2.    public static AbstractFactory getFactory(String choice){ 
  3.       if(choice.equalsIgnoreCase("SHAPE")){ 
  4.          return new ShapeFactory(); 
  5.       } else if(choice.equalsIgnoreCase("COLOR")){ 
  6.          return new ColorFactory(); 
  7.       } 
  8.       return null
  9.    } 
  • 使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象
  1. public class AbstractFactoryPatternDemo { 
  2.    public static void main(String[] args) { 
  3.   
  4.       //获取形状工厂 
  5.       AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); 
  6.   
  7.       //获取形状为 Circle 的对象 
  8.       Shape shape1 = shapeFactory.getShape("CIRCLE"); 
  9.   
  10.       //调用 Circle 的 draw 方法 
  11.       shape1.draw(); 
  12.   
  13.       //获取形状为 Rectangle 的对象 
  14.       Shape shape2 = shapeFactory.getShape("RECTANGLE"); 
  15.   
  16.       //调用 Rectangle 的 draw 方法 
  17.       shape2.draw(); 
  18.        
  19.       //获取形状为 Square 的对象 
  20.       Shape shape3 = shapeFactory.getShape("SQUARE"); 
  21.   
  22.       //调用 Square 的 draw 方法 
  23.       shape3.draw(); 
  24.   
  25.       //获取颜色工厂 
  26.       AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); 
  27.   
  28.       //获取颜色为 Red 的对象 
  29.       Color color1 = colorFactory.getColor("RED"); 
  30.   
  31.       //调用 Red 的 fill 方法 
  32.       color1.fill(); 
  33.   
  34.       //获取颜色为 Green 的对象 
  35.       Color color2 = colorFactory.getColor("Green"); 
  36.   
  37.       //调用 Green 的 fill 方法 
  38.       color2.fill(); 
  39.   
  40.       //获取颜色为 Blue 的对象 
  41.       Color color3 = colorFactory.getColor("BLUE"); 
  42.   
  43.       //调用 Blue 的 fill 方法 
  44.       color3.fill(); 
  45.    } 
  • 执行程序,输出结果:
  1. Inside Circle::draw() method. 
  2. Inside Rectangle::draw() method. 
  3. Inside Square::draw() method. 
  4. Inside Red::fill() method. 
  5. Inside Green::fill() method. 
  6. Inside Blue::fill() method. 

五、应用

工厂模式在实际开发中使用非常频繁,例如 JDK 中的日历操作,在国际化的时候,获取本地语言就用到简单工厂模式。

写一个获取测试,如下:

  1. public static void main(String[] args) { 
  2.     //获取日历操作类 
  3.     Calendar calendar = Calendar.getInstance(); 
  4.  
  5.     int year = calendar.get(Calendar.YEAR); 
  6.     // 取月份要加1 
  7.     int month = calendar.get(Calendar.MONTH) + 1; 
  8.     int day = calendar.get(Calendar.DAY_OF_MONTH); 
  9.     int hour = calendar.get(Calendar.HOUR_OF_DAY); 
  10.     int minute = calendar.get(Calendar.MINUTE); 
  11.     int seconds = calendar.get(Calendar.SECOND); 
  12.     // 1-7分别代表 -- 星期日,星期一,星期二,星期三,星期四,星期五,星期六 
  13.     int week = calendar.get(calendar.DAY_OF_WEEK); 
  14.  
  15.     // 年-月-日 
  16.     System.out.println("year = " + year); 
  17.     System.out.println("month = " + month); 
  18.     System.out.println("day = " + day); 
  19.     //时-分-秒 
  20.     System.out.println("hour = " + hour); 
  21.     System.out.println("minute = " + minute); 
  22.     System.out.println("seconds = " + seconds); 
  23.  
  24.     // 星期 
  25.     System.out.println("week = " + week); 

进入getInstance()方法,在获取日历类型的时候,内容如下:

六、小结

工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。

但要明确的,工厂模式的接口只会返回一种类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。

上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可!

七、参考

1、菜鸟教程 - 工厂模式 

2、博客园 - alpha_panda - 设计模式之工厂模式

 

责任编辑:武晓燕 来源: Java极客技术
相关推荐

2014-12-19 10:09:47

2022-01-12 13:33:25

工厂模式设计

2021-03-06 22:50:58

设计模式抽象

2011-11-17 16:03:05

Java工厂模式Clojure

2020-08-21 07:23:50

工厂模式设计

2021-09-29 13:53:17

抽象工厂模式

2020-10-19 09:28:00

抽象工厂模式

2010-04-19 09:30:00

工厂模式PHP设计模式

2009-01-15 10:55:29

JavaScript设计模式抽象工厂

2022-05-09 08:04:50

工厂模式设计模式

2010-10-09 09:25:35

Python工厂模式

2013-11-26 16:29:22

Android设计模式

2011-07-28 09:50:58

设计模式

2015-11-03 09:43:43

avascript设计模式工厂模式

2019-08-16 10:46:46

JavaScript工厂模式抽象工厂模式

2020-08-11 11:20:30

Typescript设计模式

2023-03-27 00:20:48

2020-12-17 09:38:16

设计模式参数

2024-02-20 12:09:32

模式工厂方法接口

2011-07-21 14:33:02

设计模式
点赞
收藏

51CTO技术栈公众号