Pulpcode

捕获,搅碎,拼接,吞咽

0%

从python到java设计模式之抽象工厂模式

之前的博客提到过设计模式的主要思路就是直接通过接口(实现接口),或者间接通过接口(中间对象)来进行解耦的,并介绍了两种行为型设计模式,命令模式和策略模式,这次介绍一个来自创建型模式的抽象工厂模式。

简单工厂

其实在创建型模式中,有一种常常被用来举例,却没有归类到真正的设计模式中,就是简单工厂模式。

比如如下创建对象的方式,让创建对象的方式变得耦合。

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开发中,我很难想到,为啥要用抽象工厂来创造产品簇。