工厂方法模式(Factory Pattern)属于创建型模式,它提供了一种创建对象的最佳方式,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

场景

明确地计划不同条件下创建不同实例

实现

创建一个接口。

Shape.java

  1. public interface Shape {
  2. void draw();
  3. }

创建实现接口的实体类。

Rectangle.java

  1. public class Rectangle implements Shape {
  2. @Override
  3. public void draw() {
  4. System.out.println("Inside Rectangle::draw() method.");
  5. }
  6. }

Square.java

  1. public class Square implements Shape {
  2. @Override
  3. public void draw() {
  4. System.out.println("Inside Square::draw() method.");
  5. }
  6. }

Circle.java

  1. public class Circle implements Shape {
  2. @Override
  3. public void draw() {
  4. System.out.println("Inside Circle::draw() method.");
  5. }
  6. }

抽象工厂类

Factory.Java

  1. public interface Factory {
  2. void getShape(String shapeType);
  3. }

创建一个工厂,生成基于给定信息的实体类的对象。

ShapeFactory.java

  1. public class ShapeFactory implements Factory {
  2. @Override
  3. public Shape getShape(String shapeType){
  4. if(shapeType == null){
  5. return null;
  6. }
  7. if(shapeType.equalsIgnoreCase("CIRCLE")){
  8. return new Circle();
  9. } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
  10. return new Rectangle();
  11. } else if(shapeType.equalsIgnoreCase("SQUARE")){
  12. return new Square();
  13. }
  14. return null;
  15. }
  16. }

此处的工厂实现会带来一个问题:如果我们去增加Shape,那就需要在工厂类中在添加一个If else或者Case分支条件,这违背了开放封闭原则,我们对修改也开放了,所以工厂实现还有另外一种实现方式

扩展:工厂实现的另外一种方式(反射)
  1. public class ShapeFactory {
  2. public <T extends Shape> T getShape(Class<T> shapeClass) {
  3. Shape shape = null;
  4. String shapeName = shapeClass.getName();
  5. try {
  6. shape = (Shape) Class.forName(shapeName).newInstance();
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. }
  10. return (T) shape;
  11. }
  12. }

使用这种工厂的实现方式,当需要增加Shape时,并不需要修改工厂类,直接创建Shape即可。

扩展:工厂扩展为多个工厂

为每一个Shape,创建一个单独的工厂,各司其职,比如

  1. public class SquareFactory implements Factory{
  2. @Override
  3. public Shape getShape(String shapeType){
  4. return new Square();
  5. }
  6. }

优点

  • 良好的封装性,代码结构清晰
  • 扩展性高,如果想增加一个产品,只要扩展或者修改一个工厂类就可以
  • 屏蔽产品的具体实现,调用者只关心产品的接口

缺点

  • 每次增加一个产品时,都需要增加一个具体类和对象,使得系统中类的个数成倍增加

Android 中的应用

Java中的类集合框架

List和Set继承自Collection接口,Collection接口继承于Iterable接口

  1. public interface Iterable<T> {
  2. Iterator<T> iterator();
  3. }

List 的间接实现类ArrayList中:

  1. public Iterator<E> iterator() {
  2. return new Itr();
  3. }

分析:
Iterator -> Shape(产品抽象)
Itr -> 具体的Shape(具体产品实现)
List/Collection/Iterable -> Factory(工厂抽象)
ArrayList -> SquareFactory (具体的工厂实现)

参考

书籍:《设计模式之禅》、《Android源码设计模式》
技术文章:菜鸟教程-设计模式