设计模式系列-工厂模式

工厂模式有三种,简单工厂模式,工厂方法模式以及抽象工厂模式。其中我们通常所说的工厂模式指的是工厂方法模式,工厂方法模式是日常开发中使用频率最高的一种设计模式,甚至在Android的源码中也是随处可见。

简单工厂模式

适用场景:

其实由定义也大概能推测出其使用场景,首先由于只有一个工厂类,所以工厂类中创建的对象不能太多,否则工厂类的业务逻辑就太复杂了,其次由于工厂类封装了对象的创建过程,所以客户端应该不关心对象的创建。总结一下适用场景:

  1. 需要创建的对象较少。
  2. 客户端不关心对象的创建过程。

实例

实例:
  创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会有一个draw()方法用于绘图,不看代码先考虑一下如何通过该模式设计完成此功能。

  由题可知圆形,正方形,三角形都属于一种图形,并且都具有draw方法,所以首先可以定义一个接口或者抽象类,作为这三个图像的公共父类,并在其中声明一个公共的draw方法。

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

  这里定义成抽象类也是可以的,只不过接口是更高一级的抽象,所以习惯定义成接口,而且接口支持多实现,方便以后扩展。

下面就是编写具体的图形,每种图形都实现Shape 接口
圆形

1
2
3
4
5
6
7
8
9
10
11
12
public class CircleShape implements Shape {

public CircleShape() {
System.out.println( "CircleShape: created");
}

@Override
public void draw() {
System.out.println( "draw: CircleShape");
}

}

正方形

1
2
3
4
5
6
7
8
9
10
11
public class RectShape implements Shape {
public RectShape() {
System.out.println( "RectShape: created");
}

@Override
public void draw() {
System.out.println( "draw: RectShape");
}

}

三角形

1
2
3
4
5
6
7
8
9
10
11
12
public class TriangleShape implements Shape {

public TriangleShape() {
System.out.println( "TriangleShape: created");
}

@Override
public void draw() {
System.out.println( "draw: TriangleShape");
}

}

下面是工厂类的具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ShapeFactory {
public static final String TAG = "ShapeFactory";
public static Shape getShape(String type) {
Shape shape = null;
if (type.equalsIgnoreCase("circle")) {
shape = new CircleShape();
} else if (type.equalsIgnoreCase("rect")) {
shape = new RectShape();
} else if (type.equalsIgnoreCase("triangle")) {
shape = new TriangleShape();
}
return shape;
}
}

  在这个工厂类中通过传入不同的type可以new不同的形状,返回结果为Shape 类型,这个就是简单工厂核心的地方了。
客户端使用

画圆形

1
2
Shape shape= ShapeFactory.getShape("circle");
shape.draw();

画正方形

1
2
Shape shape= ShapeFactory.getShape("rect");
shape.draw();

画三角形

1
2
Shape shape= ShapeFactory.getShape("triangle");
shape.draw();

工厂方法模式

工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。(简单工厂是一个工厂,所有类型的实例创建都在这个这个工厂,新加类型就需要修改这个工程,不符合开闭原则)

工厂模式,就是每个实例都有对应的工厂,每个工厂创建各自的实例,而不是把所有的工厂混在一起。

1
2
3
4
public interface ShapeFactory {

Shape createShape();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TriangleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new TriangleShape();
}
}

public class CircleFactory implements ShapeFactory {
@Override
public Shape createShape() {
return new CircleShape();
}
}

在使用的时候,如下

1
2
3
ShapeFactory shapeFactory = new CircleFactory();
Shape shape = shapeFactory.createShape();
shape.draw();

相对比简单工厂模式,如果新增一个模式,只要新增对应的工厂即可,在简单工厂模式中,需要修改ShapeFactory 这个类,这是不利于扩展的。

抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。( 在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的对象)

  
抽象工厂和工厂方法一样可以划分为4大部分:

  • AbstractFactory(抽象工厂)声明了一组用于创建对象的方法,注意是一组。
  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建对象的方法,生成一组具体对象。
  • AbstractProduct(抽象产品):它为每种对象声明接口,在其中声明了对象所具有的业务方法。
  • ConcreteProduct(具体产品):它定义具体工厂生产的具体对象。
    下面还是先看一个具体实例。

实例

现在需要做一款跨平台的游戏,需要兼容Android,Ios,Wp三个移动操作系统,该游戏针对每个系统都设计了一套操作控制器(OperationController)和界面控制器(UIController),下面通过抽象工厂方式完成这款游戏的架构设计。

抽象操作控制器

1
2
3
public interface OperationController {
void control();
}

抽象界面控制器

1
2
3
public interface UIController {
void display();
}

然后完成各个系统平台的具体操作控制器和界面控制器
Android

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AndroidOperationController implements OperationController {
@Override
public void control() {
System.out.println("AndroidOperationController");
}
}

public class AndroidUIController implements UIController {
@Override
public void display() {
System.out.println("AndroidInterfaceController");
}
}

Ios

1
2
3
4
5
6
7
8
9
10
11
12
13
public class IosOperationController implements OperationController {
@Override
public void control() {
System.out.println("IosOperationController");
}
}

public class IosUIController implements UIController {
@Override
public void display() {
System.out.println("IosInterfaceController");
}
}

Wp

1
2
3
4
5
6
7
8
9
10
11
12
public class WpOperationController implements OperationController {
@Override
public void control() {
System.out.println("WpOperationController");
}
}
public class WpUIController implements UIController {
@Override
public void display() {
System.out.println("WpInterfaceController");
}
}

下面定义一个抽象工厂,该工厂需要可以创建OperationController和UIController

1
2
3
4
public interface SystemFactory {
public OperationController createOperationController();
public UIController createInterfaceController();
}

在各平台具体的工厂类中完成操作控制器和界面控制器的创建过程

Android

1
2
3
4
5
6
7
8
9
10
11
public class AndroidFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new AndroidOperationController();
}

@Override
public UIController createInterfaceController() {
return new AndroidUIController();
}
}

Ios

1
2
3
4
5
6
7
8
9
10
11
public class IosFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new IosOperationController();
}

@Override
public UIController createInterfaceController() {
return new IosUIController();
}
}

Wp

1
2
3
4
5
6
7
8
9
10
11
public class WpFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new WpOperationController();
}

@Override
public UIController createInterfaceController() {
return new WpUIController();
}
}

客户端调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SystemFactory mFactory;
UIController interfaceController;
OperationController operationController;

//Android
mFactory=new AndroidFactory();
//Ios
mFactory=new IosFactory();
//Wp
mFactory=new WpFactory();

interfaceController=mFactory.createInterfaceController();
operationController=mFactory.createOperationController();
interfaceController.display();
operationController.control();

如果使用工厂方法而不是抽象工厂,那么每个平台的每个ui需要一个工厂,每个controller需要一个工厂,那么工厂就会很多,所以需要抽象工厂,将ui和controller抽象出一个工厂。