1. design-patterns/

golang 外观模式讲解和代码示例

·460 字·3 分钟· loading
设计模式 设计模式 golang
demo007x
作者
demo007x
设计模式 - This article is part of a series.
Part : This Article

Go 外观模式讲解和代码示例
#

外观是一种结构型设计模式, 能为复杂系统、 程序库或框架提供一个简单 (但有限) 的接口。

尽管外观模式降低了程序的整体复杂度, 但它同时也有助于将不需要的依赖移动到同一个位置。

概念示例
#

人们很容易低估使用信用卡订购披萨时幕后工作的复杂程度。 在整个过程中会有不少的子系统发挥作用。 下面是其中的一部分:

  • 检查账户
  • 检查安全码
  • 借记/贷记余额
  • 账簿录入
  • 发送消息通知

在如此复杂的系统中, 可以说是一步错步步错, 很容易就会引发大的问题。 这就是为什么我们需要外观模式, 让客户端可以使用一个简单的接口来处理众多组件。 客户端只需要输入卡片详情、 安全码、 支付金额以及操作类型即可。

外观模式会与多种组件进一步地进行沟通, 而又不会向客户端暴露其内部的复杂性。

walletFacade.go: 外观
#

package main

import (
	"fmt"
)

type WalletFacade struct {
	account      *Account
	wallet       *Wallet
	securityCode *SecurityCode
	notification *Notification
	ledger       *Ledger
}

func newWalletFacade(accountID string, code int) *WalletFacade {
	fmt.Println("Starting create account")
	var walletFacade = &WalletFacade{
		account:      newAccount(accountID),
		securityCode: newSecurityCode(code),
		wallet:       newWallet(),
		notification: &Notification{},
		ledger:       &Ledger{},
	}
	fmt.Println("Account created")
	return walletFacade
}

func (w *WalletFacade) addMoneyToWallet(accountID string, securityCode int, amount int) error {
	fmt.Println("Start add money to wallet")
	err := w.account.checkAccount(accountID)
	if err != nil {
		return err
	}
	err = w.securityCode.checkCode(securityCode)
	if err != nil {
		return err
	}

	w.wallet.creditBalance(amount)
	w.notification.sendWalletCreditNotification()
	w.ledger.makeEntry(accountID, "credit", amount)
	return nil
}

func (w *WalletFacade) deductMoneyFromWallet(accountID string, securityCode, amount int) error {
	fmt.Println("Starting debit money from wallet")
	err := w.account.checkAccount(accountID)
	if err != nil {
		return err
	}
	err = w.securityCode.checkCode(securityCode)
	if err != nil {
		return err
	}

	err = w.wallet.debitBalance(amount)
	if err != nil {
		return err
	}
	w.notification.sendWalletCreditNotification()
	w.ledger.makeEntry(accountID, "debit", amount)
	return nil
}

account.go: 复杂子系统的组成部分
#

package main

import "fmt"

type Account struct {
	name string
}

func newAccount(name string) *Account {
	return &Account{
		name: name,
	}
}

func (a *Account) checkAccount(name string) error {
	if a.name != name {
		return fmt.Errorf("Account Name is incorrect")
	}
	fmt.Println("Account Verified")
	return nil
}

securityCode.go: 复杂子系统的组成部分
#

package main

import "fmt"

type SecurityCode struct {
	code int
}

func newSecurityCode(code int) *SecurityCode {
	return &SecurityCode{code: code}
}

func (s *SecurityCode) checkCode(incomingCode int) error {
	if s.code != incomingCode {
		return fmt.Errorf("Security Code is incorrect")
	}
	fmt.Println("SecurityCode Verified")
	return nil
}

wallet.go: 复杂子系统的组成部分
#

package main

import "fmt"

type Wallet struct {
	balance int
}

func newWallet() *Wallet {
	return &Wallet{balance: 0}
}

func (w *Wallet) creditBalance(amount int) {
	w.balance += amount
	fmt.Println("Wallet balance added successfully")
	return
}

func (w *Wallet) debitBalance(amount int) error {
	if w.balance < amount {
		return fmt.Errorf("Balance is not sufficient")
	}
	w.balance -= amount
	return nil
}

ledger.go: 复杂子系统的组成部分
#

package main

import "fmt"

type Ledger struct{}

func (s *Ledger) makeEntry(accountID, txnType string, amount int) {
	fmt.Printf("Make ledger entry for accountId %s with txnType %s for amount %d\n", accountID, txnType, amount)
	return
}

notification.go: 复杂子系统的组成部分
#

package main

import "fmt"

type Notification struct{}

func (n *Notification) sendWalletCreditNotification() {
	fmt.Println("sending wallet credit notification")
}

func (n *Notification) sendWalletDebitNotification() {
	fmt.Println("Sending wallet debit notification")
}

main.go: 客户端代码
#

package main

import (
	"fmt"
	"log"
)

func main() {
	fmt.Println()
	walletFacade := newWalletFacade("abc", 1234)
	fmt.Println()
	err := walletFacade.addMoneyToWallet("abc", 1234, 10)
	if err != nil {
		log.Fatalf("error: %s \n", err.Error())
	}
	fmt.Println()
	err = walletFacade.deductMoneyFromWallet("abc", 1234, 5)
	if err != nil {
		log.Fatalf("error: %s \n", err.Error())
	}
}

output.txt: 执行结果
#

设计模式 - This article is part of a series.
Part : This Article

Related

golang 装饰模式讲解和代码示例
设计模式 设计模式 golang
装饰是一种结构设计模式, 允许你通过将对象放入特殊封装对象中来为原对象增加新的行为。由于目标对象和装饰器遵循同一接口, 因此你可用装饰来对对象进行无限次的封装。 结果对象将获得所有封装器叠加而来的行为。
golang 组合模式讲解和代码示例
设计模式 设计模式 golang
组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。对于绝大多数需要生成树状结构的问题来说, 组合都是非常受欢迎的解决方案。 组合最主要的功能是在整个树状结构上递归调用方法并对结果进行汇总。
golang 命令模式讲解和代码示例
设计模式 设计模式 golang
命令是一种行为设计模式, 它可将请求或简单操作转换为一个对象。此类转换让你能够延迟进行或远程执行请求, 还可将其放入队列中。