Skip to content

Commit

Permalink
新增创建资源对象流程模式
Browse files Browse the repository at this point in the history
  • Loading branch information
googs1025 committed Nov 14, 2023
1 parent 6b03585 commit c5ed11f
Show file tree
Hide file tree
Showing 12 changed files with 295 additions and 8 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
1. **代理模式**:可以和装饰器模式进一步解耦。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/proxy-pattern)
2. **装饰器模式**:基本常见。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/decorator-pattern)
3. **中间件模式**:基本常见。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/middleware-pattern)
3. **适配器模式**:救火专用模式。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/wrapper-adapter-pattern)
4. **桥接模式**:拆分抽象与具体实现。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/bridge-pattern)
5. **选项模式**:初始化参数传递。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/option-pattern)
4. **适配器模式**:救火专用模式。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/wrapper-adapter-pattern)
5. **桥接模式**:拆分抽象与具体实现。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/bridge-pattern)
6. **选项模式**:初始化参数传递。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Structural/option-pattern)

### 行为模式:
1. **责任链模式**:一个对象或请求有流程化需求。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Behavioral/chain-of-responsibility-pattern)
Expand All @@ -23,3 +23,7 @@
5. **模版模式** 模版模式与策略模式非常容易混淆。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Behavioral/template-pattern)
6. **观察者模式**:当一个对象状态被修改时,会通知"观察"它的对象。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Behavioral/subject-object-pattern)
7. **缓存代理模式**:当读取或是执行耗时长的请求或操作时,可以使用。 [代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/Behavioral/cache-proxy-pattern)

### Other 模式:
1. **创建资源对象模式**:模拟创建资源对象,并可扩展多个 hook 方法。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/other/create-resource-pattern)
2. **goroutine 模式**:并发简易示例。[代码示例](https://github.com/StudyPlace-io/Golang-Design-Pattern-Demo/tree/main/other/gouroutine-pattern)
2 changes: 1 addition & 1 deletion Structural/middleware-pattern/middleware_pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (c *Context) Run() {
firstFunc(c)
}

// 类似gin的GET方法 (PUT POST ... 等)
// GET 类似gin的GET方法 (PUT POST ... 等)
func (c *Context) GET(path string, f MainFunc) {
// 记得需要加入的中间件后面!!!
c.handlers = append(c.handlers, f)
Expand Down
11 changes: 9 additions & 2 deletions Structural/middleware-pattern/middleware_pattern_another_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import (
"fmt"
"net/http"
"testing"
"time"
)

func TestMiddlewarePattern1(t *testing.T) {

// 加入中间件,第一个入参:主handler,后面可传入多个中间件。
handler := ApplyMiddleware(MyHandler, LoggerMiddleware)
fmt.Println("httpserver start!!")
http.ListenAndServe(":8080", handler)
go func() {
fmt.Println("httpserver start!!")
http.ListenAndServe(":8080", handler)
}()

ch := time.After(time.Second * 10)

<-ch

}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module golanglearning/new_project/for-gong-zhong-hao/Design-Patterns-practice
module github.com/practice/Design-Patterns-practice

go 1.18

Expand Down
2 changes: 1 addition & 1 deletion other/Go-gorm-practice/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"errors"
"fmt"
model "golanglearning/new_project/for-gong-zhong-hao/Design-Patterns-practice/other/Go-gorm-practice/gorm_demo"
model "github.com/practice/Design-Patterns-practice/other/Go-gorm-practice/gorm_demo"
"gorm.io/gorm"
"log"
"math/rand"
Expand Down
27 changes: 27 additions & 0 deletions other/create-resource-pattern/hook/auth_hook/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package auth_hook

import (
"fmt"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/resource"
)

// AuthHook 是身份验证的钩子实现
type AuthHook struct {
Username string
Password string
}

// BeforeCreate 在创建资源之前执行的钩子函数
func (h *AuthHook) BeforeCreate(resource *resource.Resource) error {
// 模拟身份验证逻辑
if h.Username != "admin" || h.Password != "password" {
return fmt.Errorf("authentication failed")
}
return nil
}

// AfterCreate 在创建资源之后执行的钩子函数
func (h *AuthHook) AfterCreate(resource *resource.Resource) error {
fmt.Printf("Resource with ID %s created successfully\n", resource.ID)
return nil
}
9 changes: 9 additions & 0 deletions other/create-resource-pattern/hook/interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package hook

import "github.com/practice/Design-Patterns-practice/other/create-resource-pattern/resource"

// ResourceHook 创建资源时的钩子方法
type ResourceHook interface {
BeforeCreate(resource *resource.Resource) error
AfterCreate(resource *resource.Resource) error
}
23 changes: 23 additions & 0 deletions other/create-resource-pattern/hook/log_hook/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package log_hook

import (
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/resource"
"log"
)

// LoggingHook 是日志记录的钩子实现
type LoggingHook struct {
Logger *log.Logger
}

// BeforeCreate 在创建资源之前执行的钩子函数
func (h *LoggingHook) BeforeCreate(resource *resource.Resource) error {
h.Logger.Printf("Creating resource with ID: %s\n", resource.ID)
return nil
}

// AfterCreate 在创建资源之后执行的钩子函数
func (h *LoggingHook) AfterCreate(resource *resource.Resource) error {
h.Logger.Printf("Resource with ID %s created successfully\n", resource.ID)
return nil
}
26 changes: 26 additions & 0 deletions other/create-resource-pattern/hook/validator_hook/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package validator_hook

import (
"fmt"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/resource"
"regexp"
)

// EmailValidatorHook 是电子邮件验证的钩子实现
type EmailValidatorHook struct {
EmailRegex *regexp.Regexp
}

// BeforeCreate 在验证用户之前执行的钩子函数
func (h *EmailValidatorHook) BeforeCreate(resource *resource.Resource) error {
if !h.EmailRegex.MatchString(resource.Email) {
return fmt.Errorf("invalid email address")
}
return nil
}

// AfterCreate 在验证用户之后执行的钩子函数
func (h *EmailValidatorHook) AfterCreate(resource *resource.Resource) error {
fmt.Printf("User with ID %s validated successfully\n", resource.ID)
return nil
}
108 changes: 108 additions & 0 deletions other/create-resource-pattern/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package create_resource_pattern

import (
"fmt"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/hook"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/resource"
"sync"
)

// ResourceManager 是资源对象的管理器
type ResourceManager struct {
mu sync.Mutex
resources map[string]*resource.Resource
beforeFn []func(resource *resource.Resource) error
afterFn []func(resource *resource.Resource) error
}

// NewResourceManager 创建一个新的资源管理器
func NewResourceManager() *ResourceManager {
return &ResourceManager{
resources: make(map[string]*resource.Resource),
}
}

// RegisterHook 注册资源对象的钩子
func (rm *ResourceManager) RegisterHook(hook hook.ResourceHook) {
rm.beforeFn = append(rm.beforeFn, hook.BeforeCreate)
rm.afterFn = append(rm.afterFn, hook.AfterCreate)
}

// CreateResource 创建一个新的资源对象
func (rm *ResourceManager) CreateResource(id, name, email string) error {
rm.mu.Lock()
defer rm.mu.Unlock()

var err error
// 如果 hook 流程出错,默认不创建资源对象
defer func() {
if err != nil {
delete(rm.resources, id)
}
}()

if _, exists := rm.resources[id]; exists {
return fmt.Errorf("resource with ID %s already exists", id)
}

rr := &resource.Resource{
ID: id,
Name: name,
Email: email,
// 设置其他属性...
}

// 执行创建前的钩子函数
for _, beforeFn := range rm.beforeFn {
err = beforeFn(rr)
if err != nil {
return err
}
}

rm.resources[id] = rr

// 执行创建后的钩子函数
for _, afterFn := range rm.afterFn {
err = afterFn(rr)
if err != nil {
return err
}
}

return nil
}

// GetResourceByID 根据资源 ID 获取资源对象
func (rm *ResourceManager) GetResourceByID(id string) (*resource.Resource, error) {
rm.mu.Lock()
defer rm.mu.Unlock()

r, exists := rm.resources[id]
if !exists {
return nil, fmt.Errorf("resource with ID %s does not exist", id)
}

return r, nil
}

func (rm *ResourceManager) DeleteResourceByID(id string) error {
rm.mu.Lock()
defer rm.mu.Unlock()

delete(rm.resources, id)
return nil
}

// ListResources 返回所有资源对象的列表
func (rm *ResourceManager) ListResources() []*resource.Resource {
rm.mu.Lock()
defer rm.mu.Unlock()

resources := make([]*resource.Resource, 0, len(rm.resources))
for _, r := range rm.resources {
resources = append(resources, r)
}

return resources
}
74 changes: 74 additions & 0 deletions other/create-resource-pattern/manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package create_resource_pattern

import (
"fmt"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/hook/auth_hook"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/hook/log_hook"
"github.com/practice/Design-Patterns-practice/other/create-resource-pattern/hook/validator_hook"
"log"
"regexp"
"testing"
)

func TestResourceManager(t *testing.T) {
rm := NewResourceManager()

// 创建一个身份验证钩子对象
authHook := &auth_hook.AuthHook{
Username: "admin",
Password: "password",
}

// 注册身份验证钩子
rm.RegisterHook(authHook)

// 创建一个日志记录钩子对象
logger := log.New(log.Writer(), "", log.LstdFlags)
loggingHook := &log_hook.LoggingHook{
Logger: logger,
}

// 注册日志记录钩子
rm.RegisterHook(loggingHook)

// 创建一个电子邮件验证钩子对象
emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)

emailValidator := &validator_hook.EmailValidatorHook{
EmailRegex: emailRegex,
}

rm.RegisterHook(emailValidator)

err := rm.CreateResource("1", "Resource 1", "[email protected]")
if err != nil {
fmt.Println("Error creating resource:", err)
return
}

err = rm.CreateResource("2", "Resource 2", "[email protected]")
if err != nil {
fmt.Println("Error创建资源:", err)
return
}

resources := rm.ListResources()
fmt.Println("Resources:")
for _, resource := range resources {
fmt.Printf("ID: %s, Name: %s\n", resource.ID, resource.Name)
}

resource, err := rm.GetResourceByID("1")
if err != nil {
fmt.Println("Error getting resource:", err)
return
}

err = rm.DeleteResourceByID("1")
if err != nil {
fmt.Println("Error deleting resource:", err)
return
}

fmt.Println("Resource 1 Name:", resource.Name)
}
9 changes: 9 additions & 0 deletions other/create-resource-pattern/resource/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package resource

// Resource 是一个示例资源对象
type Resource struct {
ID string
Name string
Email string
// 添加其他属性...
}

0 comments on commit c5ed11f

Please sign in to comment.