之前的博客提到过设计模式的主要思路就是直接通过接口(实现接口),或者间接通过接口(中间对象)来进行解耦的,并介绍了两种行为型设计模式,命令模式和策略模式,这次介绍一个来自创建型模式的抽象工厂模式。
简单工厂
其实在创建型模式中,有一种常常被用来举例,却没有归类到真正的设计模式中,就是简单工厂模式。
比如如下创建对象的方式,让创建对象的方式变得耦合。
1
| Pencil pencil = new Pencil();
|
我们想通过某种方式,让获得创建对象的方式,变得更灵活。
这时候只需要让所有文具都继承文具基类,然后从工厂简介创建对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public abstract class Stationery{ xxxxx }
public class Pencil extends Stationery{ xxxxx }
public class Eraser extends Stationery{ xxxxx }
public class StationeryFactory{ public Stationery create(){ xxxx } }
Stationery stationery = StationeryFactory().create();
|
这样你可以根据某些灵活的配置或者逻辑创建一个对象(这样的话,create中可能就是简单的if else代码了),更有意思的是,你甚至都不知道自己到底是否在创建一个对象。还是获得了一个单例对象,又或者是提前创建好的池对象。(可以类比python获得logging对象)
之所以提到简单工厂模式,确实是因为简单工厂能够说明,这些创建型模式,其实就是为了把创建对象变得更灵活。
抽象工厂模式
抽象工厂模式的目的,是为了创造一种产品簇,在GUI跨平台解决方案,就会使用到创建者模式的抽象工厂模式。比如你的java GUI,像是这些Text,Diagram,Rectangle这些标准化的模块,虽然在不同平台上的实现方式(linux, windows,mac),可能有所不同,但是它们使用起来,暴露给外面的接口却是一样的。
而抽象工厂的目的,就是为了抽象出一类产品簇的创建方式,这样如果要添加新的产品簇也不用修改旧代码。只需实现抽象工厂接口,提供对应的产品簇就行了。
在《设计模式》这本书中,使用游戏开发中的迷宫创建程序来举这个抽象工厂的例子。
java实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public abstract class MazeFactory{ public abstract Maze makeMaze(); public abstract Wall makeWall(); public abstract Room makeRoom(int n); public abstract Door makeDoor(Room r1, Room r2);
}
public class EnchantedMazeFactory extends MazeFactory{ xxx... }
public class BombedMazeFactory extends MazeFactory{ xxx... }
public abstract class Maze(){ xxx... }
public abstract class Wall(){ xxx... }
public abstract class Room(){ xxx... }
public abstract class Door(){ xxx... }
public class EnchantedMaze extend Maze{ xxx... }
public class EnchantedWall extend Wall{ xxx... }
...
|
在某个方法中,你可能这样使用此工厂:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public Maze createMaze(MazeFactory factory){ Maze maze = factory.makeMaze(); Room r1 = factory.MakeRoom(1); Room r2 = factory.MakeRoom(2); maze.addRoom(r1); maze.addRoom(r2);
...
return maze; }
|
看,实际上,你也不知道到底是什么样的工厂被传递进来了。
python实现
首先你要知道python根本没必要从接口继承。
而且作为抽象工厂模式,工厂完全作为类就够用了,完全没必要用它创建什么工厂对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class MazeFactory(object):
@classmethod def make_maze(cls, xxx): xxxx
@classmethod def make_wall(cls, xxx): xxxx
@classmethod def make_room(cls, xxx): xxxx
@classmethod def make_door(cls, xxx): xxxx
|
所以我说抽象工厂模式,在GUI和游戏编程可能用的比较多,在web开发中,我很难想到,为啥要用抽象工厂来创造产品簇。