一、情景
Tony作為一名合格軟件工程師要學(xué)會組裝一臺自己的電腦济蝉。一臺電腦的組成:主板杰刽、電源,而主板上又有CPU王滤、硬盤贺嫂、顯卡。顯示器需要單獨插電源才能工作雁乡。
程序模擬場景
package main
import "fmt"
/********************************基礎(chǔ)組件**********************************************/
type ComputerComponent struct {
name string
}
func (c *ComputerComponent) isComposite() bool {
return false
}
func (c *ComputerComponent)startUp(indent string){
fmt.Printf("%s%s準(zhǔn)備開始工作...\n",indent, c.name)
}
func (c *ComputerComponent)shutdown(indent string){
fmt.Printf("%s%s即將結(jié)束工作...\n", indent,c.name)
}
func NewComponent(name string)*ComputerComponent{
return &ComputerComponent{
name: name,
}
}
/********************************實際組件**********************************************/
type CPU struct {
/*處理器*/
*ComputerComponent
}
func (c *CPU)showInfo(indent string){
fmt.Printf("%sCPU:%s, 可以進行高速計算第喳。\n",indent, c.name)
}
func NewCpu(name string) *CPU{
return &CPU{
ComputerComponent:NewComponent(name),
}
}
type MemoryCard struct {
/*內(nèi)存*/
*ComputerComponent
}
func NewMemory(name string) *MemoryCard {
return &MemoryCard{
ComputerComponent:NewComponent(name),
}
}
func (m *MemoryCard)showInfo(indent string){
fmt.Printf("%s內(nèi)存:%s,可以緩存數(shù)據(jù),讀寫速度塊蔗怠。\n", indent, m.name)
}
type HardDisk struct {
/*硬盤*/
*ComputerComponent
}
func (h *HardDisk)showInfo(indent string){
fmt.Printf("%s硬盤:%s,可以永久存儲數(shù)據(jù)墩弯,容量大吩跋。\n",indent,h.name)
}
func NewHardDisk(name string) *HardDisk{
return &HardDisk{
ComputerComponent:NewComponent(name),
}
}
type GraphicsCard struct {
/*顯卡*/
*ComputerComponent
}
func (g *GraphicsCard)showInfo(indent string){
fmt.Printf("%s顯卡:%s寞射,可以高速計算和處理圖形圖像。\n",indent,g.name)
}
func NewGraphics(name string)* GraphicsCard{
return &GraphicsCard{
ComputerComponent:NewComponent(name),
}
}
type Battery struct {
/*電源*/
*ComputerComponent
}
func (b *Battery)showInfo(indent string){
fmt.Printf("%s電源:%s锌钮,可以持續(xù)給主板和外接配件供電桥温。\n",indent)
}
func NewBattery(name string) *Battery {
return &Battery{
ComputerComponent:NewComponent(name),
}
}
type Fan struct {
/*風(fēng)扇*/
*ComputerComponent
}
func (f *Fan)showInfo(indent string){
fmt.Printf("%s風(fēng)扇:%s,輔助CPU散熱梁丘。\n",indent,f.name)
}
func NewFan(name string)*Fan{
return &Fan{
ComputerComponent:NewComponent(name),
}
}
type DisPlayer struct {
/*顯示器*/
*ComputerComponent
}
func (d *DisPlayer)showInfo(indent string){
fmt.Printf("%s顯示器:%s侵浸,負(fù)責(zé)內(nèi)容的顯示。\n",indent,d.name)
}
func NewDisPlayer(name string) *DisPlayer {
return &DisPlayer{
ComputerComponent:NewComponent(name),
}
}
/**********************************抽象組件********************************************/
type Part interface {
showInfo(indent string)
startUp(indent string)
shutdown(indent string)
}
/***********************************配件組合器*******************************************/
type ComputerComposite struct {
/*配件組合器*/
*ComputerComponent
Components []Part
}
func (c *ComputerComposite)showInfo(indent string){
fmt.Printf("%s氛谜,由以下部件組成:\n", c.name)
indent += "\t"
for i:=0;i<len(c.Components);i++{
c.Components[i].showInfo(indent)
}
}
func (c *ComputerComposite)isComposite()bool{
return true
}
func (c *ComputerComposite) addComponent(component Part) {
c.Components = append(c.Components, component)
}
func (c *ComputerComposite)startUp(indent string){
c.ComputerComponent.startUp(indent)
indent += "\t"
for i:=0;i<len(c.Components);i++{
c.Components[i].startUp(indent)
}
}
func (c *ComputerComposite)shutdown(indent string){
c.ComputerComponent.shutdown(indent)
indent += "\t"
for i:=0; i<len(c.Components);i++{
c.Components[i].shutdown(indent)
}
}
func NewComposite(name string) *ComputerComposite{
return &ComputerComposite{
ComputerComponent:NewComponent(name),
}
}
/*******************************組裝組件************************************************/
type MainBoard struct {
/*主板*/
*ComputerComposite
}
func (m *MainBoard)showInfo(indent string){
fmt.Printf(indent + "主板:")
m.ComputerComposite.showInfo(indent)
}
func NewMainBoard(name string)*MainBoard{
return &MainBoard{
ComputerComposite:NewComposite(name),
}
}
type ComputerCase struct {
/*機箱*/
*ComputerComposite
}
func (c *ComputerCase)showInfo(indent string){
fmt.Printf(indent+"機箱:")
c.ComputerComposite.showInfo(indent)
}
func NewComputerCase(name string)*ComputerCase{
return &ComputerCase{
ComputerComposite:NewComposite(name),
}
}
/********************************電腦整機**********************************************/
type Computer struct {
/*電腦*/
*ComputerComposite
}
func (c *Computer)showInfo(indent string){
fmt.Printf(indent + "電腦:")
c.ComputerComposite.showInfo(indent)
}
func NewComputer(name string)*Computer{
return &Computer{
NewComposite(name),
}
}
func testComputer(){
mainBoard := NewMainBoard("GIGABYTE Z170M M-atx")
cpu := NewCpu("Intel core I5-6600k")
memoryCard := NewMemory("Kingston Fury DDR4")
hardDisk := NewHardDisk("Kingston v300")
graphicsCard := NewGraphics("Colorful iGame750")
mainBoard.addComponent(cpu)
mainBoard.addComponent(memoryCard)
mainBoard.addComponent(hardDisk)
mainBoard.addComponent(graphicsCard)
battery := NewBattery("Antec vp 450p")
fan := NewFan("DEEPCOOL 120T")
computerCase := NewComputerCase("SAMA MATX")
computerCase.addComponent(mainBoard)
computerCase.addComponent(battery)
computerCase.addComponent(fan)
disPlayer := NewDisPlayer("AOC Lv243xip")
computer := NewComputer("Tony DIY 電腦")
computer.addComponent(computerCase)
computer.addComponent(disPlayer)
computer.showInfo("")
fmt.Printf("\n開機過程:\n")
computer.startUp("")
fmt.Printf("\n關(guān)機過程:\n")
computer.shutdown("")
}
func main() {
testComputer()
}
輸出結(jié)果:
電腦:Tony DIY 電腦掏觉,由以下部件組成:
機箱:SAMA MATX,由以下部件組成:
主板:GIGABYTE Z170M M-atx值漫,由以下部件組成:
CPU:Intel core I5-6600k, 可以進行高速計算澳腹。
內(nèi)存:Kingston Fury DDR4,可以緩存數(shù)據(jù),讀寫速度塊。
硬盤:Kingston v300,可以永久存儲數(shù)據(jù)酱塔,容量大沥邻。
顯卡:Colorful iGame750,可以高速計算和處理圖形圖像羊娃。
電源:%!s(MISSING)唐全,可以持續(xù)給主板和外接配件供電。
風(fēng)扇:DEEPCOOL 120T蕊玷,輔助CPU散熱邮利。
顯示器:AOC Lv243xip,負(fù)責(zé)內(nèi)容的顯示集畅。
開機過程:
Tony DIY 電腦準(zhǔn)備開始工作...
SAMA MATX準(zhǔn)備開始工作...
GIGABYTE Z170M M-atx準(zhǔn)備開始工作...
Intel core I5-6600k準(zhǔn)備開始工作...
Kingston Fury DDR4準(zhǔn)備開始工作...
Kingston v300準(zhǔn)備開始工作...
Colorful iGame750準(zhǔn)備開始工作...
Antec vp 450p準(zhǔn)備開始工作...
DEEPCOOL 120T準(zhǔn)備開始工作...
AOC Lv243xip準(zhǔn)備開始工作...
關(guān)機過程:
Tony DIY 電腦即將結(jié)束工作...
SAMA MATX即將結(jié)束工作...
GIGABYTE Z170M M-atx即將結(jié)束工作...
Intel core I5-6600k即將結(jié)束工作...
Kingston Fury DDR4即將結(jié)束工作...
Kingston v300即將結(jié)束工作...
Colorful iGame750即將結(jié)束工作...
Antec vp 450p即將結(jié)束工作...
DEEPCOOL 120T即將結(jié)束工作...
AOC Lv243xip即將結(jié)束工作...
Process finished with exit code 0
二近弟、從劇情中思考什么是組合模式
2.1什么是組合模式
將對象組合成樹形結(jié)構(gòu)以表示“整體-部分”的層次結(jié)構(gòu)關(guān)系。組合使得用戶對單個對象和復(fù)合對象的使用具有一致性挺智。
組合模式使得用戶對單個對象和組合對象的使用具有一致性(如源碼示例中 startup與shutdown的使用)祷愉,使用組合對象就像使用一般對象一樣,不用關(guān)心內(nèi)部的組織結(jié)構(gòu)赦颇。
2.2組合模式的設(shè)計思想
Tony自己DIY組裝的電腦是由各個配件組成的二鳄,在組裝之前,就是單個CPU媒怯、硬盤订讼、顯卡等配件,不能稱為電腦扇苞,只有把它們按正確的方式組裝在一起欺殿,配合操作系統(tǒng)才能正常運行。一般人使用電腦并不會關(guān)注內(nèi)部的結(jié)構(gòu)鳖敷,只會關(guān)注一臺整機脖苏。
組裝的電腦具有明顯的部分與整體的關(guān)系,主板定踱、電源等是電腦的一部分棍潘,而主板上又有CPU、硬盤崖媚、顯卡亦歉,它們又是主板的一部分。像電腦一樣畅哑,把對象組合成樹形結(jié)構(gòu)肴楷,以表示“部分-整體”的層次結(jié)構(gòu)的程序設(shè)計模式就叫組合模式。
我們將這種層次關(guān)系轉(zhuǎn)換成對象的組合關(guān)系荠呐,如下圖
三赛蔫、模型抽象
Component是組件的基類绷杜,定義統(tǒng)一的方法feature()和isComposite(),isComposite()用于判斷一個組件是否為復(fù)合組件。ComponentImplA 和 ComponentImplB 是具體的組件濒募。Composite就是復(fù)合組件(也就是組合對象)鞭盟,復(fù)合組件可以添加或刪除組件,CompositeImplA 和CompositeImplB是具體的復(fù)合組件瑰剃。復(fù)合組件本身也是一個組件齿诉,因此組合對象可以像一般對象一樣被使用,因為它也實現(xiàn)了Component的feature()方法晌姚。
3.1模型說明
1.設(shè)計要點
在設(shè)計迭代器模式時粤剧,要注意以下兩點:
(1)理清部分與整體的關(guān)系,了解對象的組成結(jié)構(gòu)挥唠。
(2)組合模式是一種具有層次關(guān)系的樹形結(jié)構(gòu)抵恋,不能再分的葉子節(jié)點是具體的組件,也就是最小的邏輯單元宝磨;具有子節(jié)點(由多個子組件組成)的組件稱為復(fù)合組件弧关,也就是組合對象。
2.組合模式的優(yōu)缺點
優(yōu)點:
(1)調(diào)用簡單唤锉,組合對象可以像一般對象一樣使用世囊。
(2)組合對象可以自由地增加、刪除組件窿祥,可靈活地組合不同的對象株憾。
缺點:
在一些層次結(jié)構(gòu)太深的場景中,組合結(jié)構(gòu)會變得太龐雜晒衩。
四嗤瞎、應(yīng)用場景
- 對象之間具有明顯的“部分-整體”的關(guān)系時,或者具有層次關(guān)系時听系。
- 組合對象與單個對象具有相同或者類似行為(方法)贝奇,用戶希望統(tǒng)一地使用組合結(jié)構(gòu)中的所有對象