定义
简单工厂也有称静态工厂,其定义一个工厂类,根据传入的不同参数返回不同的实例,被创建的对象实例具有共同的父类或接口。其本质是只需一个工厂类,便可创建若干个不同的产品类型。
使用场景
- 需要创建的对象较少,且对象具有相同的性质,如共同父类或都实现了某接口;
- 创建的过程不需要客户端关心
UML类图
代码示例
创建一个可以绘制不同形状的绘图工具,可以绘制多种图形如圆形、三角形、矩形等。代码可如下:
/**
* 定义抽象产品类
* 可定义为抽象类或者接口,但是接口更方便扩展,且可以多继承实现>
*/
interface Shape {
void draw();
}
/**
* 具体实现产品类1
*/
class Circle implements Shape {
public Circle() {
System.out.println("Circle created");
}
@Override
public void draw() {
System.out.println("draw a circle");
}
}
/**
* 具体实现产品类2
*/
class Triangle implements Shape {
public Triangle() {
System.out.println("Triangle created");
}
@Override
public void draw() {
System.out.println("draw a triangle");
}
}
/**
* 具体实现产品类3
*/
class Rect implements Shape {
public Rect() {
System.out.println("Rect created");
}
@Override
public void draw() {
System.out.println("draw a rect");
}
}
/**
* 产品类型枚举
*/
enum ShapeType {
CIRCLE,
TRIANGLE,
RECT
}
/**
* 简单工厂/静态工厂
*/
class ShapeFactory {
public static Shape getShape(ShapeType type) {
switch (type) {
case CIRCLE:
return new Circle();
case TRIANGLE:
return new Triangle();
case RECT:
return new Rect();
}
return new Circle();
}
}
public class SimpleFactoryTest {
public static void main(String[] args) {
Shape shape = ShapeFactory.getShape(ShapeType.CIRCLE);
shape.draw();
shape = ShapeFactory.getShape(ShapeType.TRIANGLE);
shape.draw();
shape = ShapeFactory.getShape(ShapeType.RECT);
shape.draw();
}
}
最终输出结果如下:
Circle created
draw a circle
Triangle created
draw a triangle
Rect created
draw a rect
二、工厂方法模式
定义
定义一个用于创建对象的接口,让子类决定具体创建去实例化哪个类,将类的实例化延迟到其子类。 与简单工厂最大的不同在于,简单工厂只需要一个统一的工厂类便可完成所有产品对象的创建,而工厂方法模式则需要为每个产品类型定义一个工厂类,由具体的工厂类去创建具体的产品。
UML类图
代码示例 现在需要设计一个这样的图片加载类,它具有多个图片加载器,用来加载jpg,png,gif格式的图片,每个加载器都有一个read()方法,用于读取图片。下面我们完成这个图片加载类。
/**
* 首先完成图片加载其的设计,编写一个加载的公共接口
*/
interface Reader {
void read();
}
/**
* jpg图片加载器
*/
class JpgReader implements Reader {
@Override
public void read() {
System.out.println("read jpg");
}
}
/**
* png加载器
*/
class PngReader implements Reader {
@Override
public void read() {
System.out.println("read png");
}
}
/**
* gif加载器
*/
class GifReader implements Reader {
@Override
public void read() {
System.out.println("read gif");
}
}
/**
* 定义一个抽象的工厂类
*/
interface ReaderFactory {
Reader getReader();
}
/**
* jpg加载器工厂
*/
class JpgReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new JpgReader();
}
}
/**
* png加载器工厂
*/
class PngReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new PngReader();
}
}
/**
* gif加载器工厂
*/
class GifReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new GifReader();
}
}
public class FactoryTest {
public static void main(String[] args) {
ReaderFactory factory = new JpgReaderFactory();
Reader reader = factory.getReader();
reader.read();
factory = new PngReaderFactory();
reader = factory.getReader();
reader.read();
factory = new GifReaderFactory();
reader = factory.getReader();
reader.read();
}
}
输出结果:
read jpg
read png
read gif
适用场景
- 客户端不需要知道它所创建的对象的类。例子中我们不知道每个图片加载器具体叫什么名,只知道创建它的工厂名就完成了创建过程;
- 客户端可以通过子类来指定创建对应的对象。
三、抽象工厂模式
定义
提供一个创建一组相关或者相互依赖对象的接口,而不需要指定它们的具体类。每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的对象。
抽象工厂和工厂方法一样可以划分为4大部分:
-
AbstractFactory
(抽象工厂)声明了一组用于创建对象的方法,注意是一组; -
ConcreteFactory
(具体工厂):它实现了在抽象工厂中声明的创建对象的方法,生成一组具体对象; -
AbstractProduct
(抽象产品):它为每种对象声明接口,在其中声明了对象所具有的业务方法; -
ConcreteProduct
(具体产品):它定义具体工厂生产的具体对象。
UML类图
代码示例
现在需要做一款跨平台的游戏,需要兼容Android,Ios,Wp三个移动操作系统,该游戏针对每个系统都设计了一套操作控制器(OperationController)和界面控制器(UIController),下面通过抽闲工厂方式完成这款游戏的架构设计。
由题可知,游戏里边的各个平台的UIController和OperationController应该是我们最终生产的具体产品。所以新建两个抽象产品接口。
抽象操作控制器
public interface OperationController {
void control();
}
抽象界面控制器
public interface UIController {
void display();
}
然后完成各个系统平台的具体操作控制器和界面控制器
Android
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
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
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
public interface SystemFactory {
public OperationController createOperationController();
public UIController createInterfaceController();
}
在各平台具体的工厂类中完成操作控制器和界面控制器的创建过程
Android
public class AndroidFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new AndroidOperationController();
}
@Override
public UIController createInterfaceController() {
return new AndroidUIController();
}
}
iOS
public class IosFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new IosOperationController();
}
@Override
public UIController createInterfaceController() {
return new IosUIController();
}
}
WP
public class WpFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new WpOperationController();
}
@Override
public UIController createInterfaceController() {
return new WpUIController();
}
}
具体使用
public class Test{
public static void main() {
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控制器的创建。小伙伴们可以对比一下,如果这个游戏使用工厂方法模式搭建需要创建多少个工厂类呢?下面总结一下抽象工厂的适用场景。
适用场景:
- 和工厂方法一样客户端不需要知道它所创建的对象的类。
- 需要一组对象共同完成某种功能时。并且可能存在多组对象完成不同功能的情况。
- 系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)
参考链接:https://www.jianshu.com/p/83ef48ce635b