抽象工厂模式也是一种创建型模式。它是为了创造一系列或者相互依赖的对象。这便是与之前的工厂模式不同的地方。抽象工厂模式和工厂模式要解决问题的出发点是一样,都是为了使类的创建者和使用者进行分离。

工厂模式

要做一个 window 和 scrollBar,但是要有两种风格,传统风格(standard)和高级定制风格(custom)。如果按照之前我们的工厂模式来进行的话。

 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// 定义 window 和 scrollBar 的接口
interface Window {
    fun show(scrollBar: ScrollBar)
}

interface ScrollBar {
    fun scroll()
}

// 实现 标准窗口 和 标准滚动条
class StandardWindow : Window {
    override fun show(scrollBar: ScrollBar) {
        println("标准窗口 ${scrollBar.scroll()}")
    }

}

class StandardScrollBar : ScrollBar {
    override fun scroll() {
        println("标准滚动条")
    }
}

// 实现 定制化窗口 和 定制化滚动条
class CustomWindow : Window {
    override fun show(scrollBar: ScrollBar) {
        println("定制窗口 ${scrollBar.scroll()}")
    }

}

class CustomScrollBar : ScrollBar {
    override fun scroll() {
        println("定制滚动条")
    }
}

// 定制 window 工厂
interface WindowFactory {
    fun create(): Window
}

// 定制 scrollBar 工厂
interface ScrollBarFactory {
    fun create(): ScrollBar
}

// 产生 标准化窗口工厂
class StandardWindowFactory : WindowFactory {
    override fun create(): Window {
        return StandardWindow()
    }
}

// 产生 标准化滚动条工厂
class StandardScrollBarFactory : ScrollBarFactory {
    override fun create(): ScrollBar {
        return StandardScrollBar()
    }
}

// 产生 定制化窗口工厂
class CustomWindowFactory : WindowFactory {
    override fun create(): Window {
        return CustomWindow()
    }
}

// 产生 定制化滚动条工厂
class CustomScrollBarFactory : ScrollBarFactory {
    override fun create(): ScrollBar {
        return CustomScrollBar()
    }
}

fun main() {
    val windowFactory = StandardWindowFactory()
    val barFactory = StandardScrollBarFactory()
    val window = windowFactory.create()
    val bar = barFactory.create()
    window.show(bar)
}

进行这样的调整,表面看是完成了功能的设计,也将对象的产生者和使用者分离,同时扩展性增强。但是,也出现了新的问题。如果使用不正确,或者客户端调用时一不留神,客户端的代码将可能成为标准窗口中出现定制滚动条,或者定制窗口中是标准滚动条。

1
2
3
4
5
6
7
fun main() {
    val windowFactory = StandardWindowFactory()
    val barFactory = CustomScrollBarFactory()
    val window = windowFactory.create()
    val bar = barFactory.create()
    window.show(bar)
}

按照这个情况来说,生成的对象并不是匹配的。所以我们要进行优化。

工厂合并

如果将相同的工厂合并在一起,那就不会出现当前的这样情况。将相同风格的界面存放到一个工厂内,这样就不会出现上述的混搭的问题。通过同样的一个工厂生成相同的一系列

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
interface Factory {
    fun createBar(): ScrollBar
    fun createWindow(): Window
}

class CustomFactory : Factory {
    override fun createBar(): ScrollBar {
        return CustomScrollBar()
    }

    override fun createWindow(): Window {
        return CustomWindow()
    }
}

class StandardFactory:Factory {
    override fun createBar(): ScrollBar {
        return StandardScrollBar()
    }

    override fun createWindow(): Window {
        return StandardWindow()
    }
}

当工厂完成合并的时候,这样通过一个工厂就可以创造出一系列相关的类。

同时完成了在运行时完对工厂和具体类的依赖,而在编译时不会产生依赖,从而进一步进行了解耦。之前的工厂模式更像是抽象工厂模式的特例,每个工厂只生产一类型产品。