前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang语言情怀-第16期 Go 语言设计模式 工厂模式

Golang语言情怀-第16期 Go 语言设计模式 工厂模式

作者头像
李海彬
发布2021-01-21 17:21:02
6440
发布2021-01-21 17:21:02
举报
文章被收录于专栏:Golang语言社区

Golang 的结构体没有构造函数,通常可以使用工厂模式来解决这个问题。

一个结构体的声明:

代码语言:javascript
复制
package model
type Student  struct{
    Name string ...
}

因为这里的Student 的首字母S是大写的,如果我们想在其它包括创建Student 的实例(比如main包),引入model 包后,就可以直接创建Student 结构体的变量(实例)。但是问题来了,如果首字母是小写的,比如是:

代码语言:javascript
复制
type student struct{
    ...
}

那么直接使用就不行了,这时候该怎么办呢? 使用工厂模式来解决!

  • 使用工厂模式实现挎包创建结构体实例(变量)的案例: 1)如果model 包的结构体变量首字母大写,引入后,直接使用,没有问题; 例如: model包代码:
代码语言:javascript
复制
package model

// 定义一个结构体
type Student struct{
    Name string
    Score float64
}

main包代码:

代码语言:javascript
复制
package main
import (
    "fmt"
    "xxx/xx..xx/xxx/model" // src 下目录名称
)

func main(){
    var str = model.Student{
        Name : "tom",
        Score: "66.6",
    }
    fmt.Println(stu)
}
  1. 如果model 包的结构体变量首字母小写,引入后,不能直接使用,可以使用工厂模式解决:

model包代码:

代码语言:javascript
复制
package model

// 定义一个结构体
type Student struct{
    Name string
    Score float64
}

// 因为student 结构体首字母是小写,因此是只能在model 使用
// 我们通过工厂模式来解决
func NewStudent(n string, s float64)  *student{
    return &student{
        Name : n,
        Score : s,
    }
}

main包代码:

代码语言:javascript
复制
package main
import (
    "fmt"
    "xxx/xx..xx/xxx/model" // src 下目录名称
)

func main(){
   var stu = model.NewStudent("tom~", 88.8) // 返回的也是指针
    fmt.Println(stu)// &(.......)
    fmt.Println(*stu)//  返回值
    fmt.Println(stu.Score)// 这个编译器可以做(*stu) 默认处理。
}
  1. 如果结构体中score 字段首字母小写,那么,在其他包不可以直接使用该字段,我们可以通过提供一个方法来解决。

model包代码:

代码语言:javascript
复制
package model

// 定义一个结构体
type Student struct{
    Name string
    score float64
}

// 因为student 结构体首字母是小写,因此是只能在model 使用
// 我们通过工厂模式来解决
func NewStudent(n string, s float64)  *student{
    return &student{
        Name : n,
        score : s,
    }
}

//获取score 方法
func (s *student) GetScore() float64{
    // return (*s).score 
    return s.score
}

main包代码:

代码语言:javascript
复制
package main
import (
    "fmt"
    "xxx/xx..xx/xxx/model" // src 下目录名称
)

func main(){
   var stu = model.NewStudent("tom~", 88.8) // 返回的也是指针
    fmt.Println(stu)// &(.......)
    fmt.Println(*stu)//  返回值
    fmt.Println(stu.GetScore())// 这个编译器可以做(*stu) 默认处理。
}

以上讲解了工厂模式的小例子,实际在我们实际开发过程中结构要复杂一些,接下来我们就讨论下抽象工厂模式,如下:

抽象工厂模式常用于程序适配多种数据库,以达到开放扩展关闭修改的原则。

首先需要有一个思想就是数据库表结构都是固定,但是每种数据库语言存在差异性,因此使用接口规范功能,各种数据库有自己不同的语言实现,业务中也是使用接口操作,运行时根据配置实例化各种数据库实现。好处是增加新的数据库时,只需要用新的数据库语言实现即可,不用修改原来的代码。部署程序时,只需要修改配置即可适配不同的数据库。

一,数据模型(Model层)

myProject/MyORM/Model/User.go

代码语言:javascript
复制
package Model

type User struct {
    Id        int
    UID       string
    LoginName string
    PassWord  string
}

func (t *User) TableName() string {
    return "User"
}

myProject/MyORM/Model/Product.go

代码语言:javascript
复制
package Model

type Product struct {
    Id    int
    UID   string
    Name  string
    Price float64
}

func (t *Product) TableName() string {
    return "Product"
}

二,接口定义(Interface层)

myProject/MyORM/Data/IUser.go

代码语言:javascript
复制
package Data

import (
    "myProject/MyORM/Model"
)

type IUser interface {
    Add(entity *Model.User) bool
    Edit(entity *Model.User) Model.User
}

myProject/MyORM/Data/IProduct.go

代码语言:javascript
复制
package Data

import (
    "myProject/MyORM/Model"
)

type IProduct interface {
    Add(entity *Model.Product) bool
    Edit(entity *Model.Product) Model.Product
}

myProject/MyORM/Data/IProvider.go

♥ 抽象工厂接口

代码语言:javascript
复制
package Data

type IProvider interface {
    GetUser() IUser
    GetProduct() IProduct
}

三,接口实现(DAL层)

♣ 注意:Go语言的接口实现是隐式的,无须让实现接口的类型写出实现了哪些接口。这个设计被称为非侵入式设计。在类型中添加与接口签名一致的方法就可以实现该方法。

1.SQL实现

myProject/MyORM/SqlData/SqlUser.go

代码语言:javascript
复制
package SqlData

import (
    "fmt"
    "myProject/MyORM/Model"
)

type SqlUser struct {
}

func (p *SqlUser) Add(entity *Model.User) bool {
    fmt.Println("sql执行UserAdd")
    return true
}

func (p *SqlUser) Edit(entity *Model.User) Model.User {
    fmt.Println("sql执行UserEdit")
    return *entity
}

myProject/MyORM/SqlData/SqlProduct.go

代码语言:javascript
复制
package SqlData

import (
    "fmt"
    "myProject/MyORM/Model"
)

type SqlProduct struct {
}

func (p *SqlProduct) Add(entity *Model.Product) bool {
    fmt.Println("sql执行ProductAdd")
    return true
}

func (p *SqlProduct) Edit(entity *Model.Product) Model.Product {
    fmt.Println("sql执行ProductEdit")
    return *entity
}

myProject/MyORM/SqlData/SqlProvider.go

♥ SQL工厂实现

代码语言:javascript
复制
package SqlData

import (
    "myProject/MyORM/Data"
)

type SqlProvider struct {
}

func (p *SqlProvider) GetUser() Data.IUser {
    return new(SqlUser)
}

func (p *SqlProvider) GetProduct() Data.IProduct {
    return new(SqlProduct)
}

2.Mysql实现

myProject/MyORM/MysqlData/MysqlUser.go

代码语言:javascript
复制
package MysqlData

import (
    "fmt"
    "myProject/MyORM/Model"
)

type MysqlUser struct {
}

func (p *MysqlUser) Add(entity *Model.User) bool {
    fmt.Println("mysql执行UserAdd")
    return true
}

func (p *MysqlUser) Edit(entity *Model.User) Model.User {
    fmt.Println("mysql执行UserEdit")
    return *entity
}

myProject/MyORM/MysqlData/MysqlProduct.go

代码语言:javascript
复制
package MysqlData

import (
    "fmt"
    "myProject/MyORM/Model"
)

type MysqlProduct struct {
}

func (p *MysqlProduct) Add(entity *Model.Product) bool {
    fmt.Println("mysql执行ProductAdd")
    return true
}

func (p *MysqlProduct) Edit(entity *Model.Product) Model.Product {
    fmt.Println("mysql执行ProductEdit")
    return *entity
}

myProject/MyORM/MysqlData/MysqlProvider.go

♥ MYSQL工厂实现

代码语言:javascript
复制
package MysqlData

import (
    "myProject/MyORM/Data"
)

type MysqlProvider struct {
}

func (p *MysqlProvider) GetUser() Data.IUser {
    return new(MysqlUser)
}

func (p *MysqlProvider) GetProduct() Data.IProduct {
    return new(MysqlProduct)
}

三,业务逻辑(BLL层)

myProject/MyORM/Service/Factory.go

代码语言:javascript
复制
package Service

import (
    "myProject/MyORM/Data"
    "myProject/MyORM/MysqlData"
    "myProject/MyORM/SqlData"
)
// 设置配置
const db = "sql"

// 简单工厂方法,根据配置加载不同的实现库
func Provider() Data.IProvider {
    switch db {
    case "sql":
        return new(SqlData.SqlProvider)
    case "mysql":
        return new(MysqlData.MysqlProvider)
    default:
        panic("无法映射配置的数据库")
    }
}

myProject/MyORM/Service/UserService.go

代码语言:javascript
复制
package Service

import (
    "myProject/MyORM/Data"
    "myProject/MyORM/Model"
)

type UserService struct {
}

var user Data.IUser

func init() {
    user = Provider().GetUser()
}

func (u *UserService) Add(entity *Model.User) bool {
    return user.Add(entity)
}

func (u *UserService) Update(entity *Model.User) Model.User {
    return user.Edit(entity)
}

myProject/MyORM/Service/ProductService.go

代码语言:javascript
复制
package Service

import (
    "myProject/MyORM/Data"
    "myProject/MyORM/Model"
)

type ProductService struct {
}

var product Data.IProduct

func init() {
    product = Provider().GetProduct()
}

func (p *ProductService) Add(entity *Model.Product) bool {
    return product.Add(entity)
}

func (p *ProductService) Update(entity *Model.Product) Model.Product {
    return product.Edit(entity)
}

四,界面展示(UI层)

myProject/MyORM/main.go

代码语言:javascript
复制
package main

import (
    "myProject/MyORM/Model"
    "myProject/MyORM/Service"
)

func main() {
    user := &Model.User{
        Id:        1,
        UID:       "12124545",
        LoginName: "admin",
        PassWord:  "123454",
    }
    userService := new(Service.UserService)
    userService.Add(user)

    product := &Model.Product{
        Id:    1,
        UID:   "12124545",
        Name:  "苹果",
        Price: 12.5,
    }
    productService := new(Service.ProductService)
    productService.Update(product)
}

参考资料:

Go语言工厂模式

https://studygolang.com/articles/25696?fr=sidebar

Go语言抽象工厂模式

https://www.cnblogs.com/shi2310/p/10899458.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言情怀 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一,数据模型(Model层)
  • 二,接口定义(Interface层)
  • 三,接口实现(DAL层)
    • 1.SQL实现
      • 2.Mysql实现
      • 三,业务逻辑(BLL层)
      • 四,界面展示(UI层)
      相关产品与服务
      云数据库 SQL Server
      腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档