From 330861387fc0af6129a0257193ca97b8dd73fac3 Mon Sep 17 00:00:00 2001 From: VIVIMAN Date: Fri, 4 Feb 2022 18:47:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../abstract_factory/main_test.go | 23 +++++- golang_learn/data_prattern/分类.md | 72 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 golang_learn/data_prattern/分类.md diff --git a/golang_learn/data_prattern/abstract_factory/main_test.go b/golang_learn/data_prattern/abstract_factory/main_test.go index 38a084a..655a188 100644 --- a/golang_learn/data_prattern/abstract_factory/main_test.go +++ b/golang_learn/data_prattern/abstract_factory/main_test.go @@ -1,9 +1,30 @@ package abstract_factory -import "testing" +import ( + "reflect" + "testing" +) + func TestNewSimpleLunchFactory(t *testing.T) { NewSimpleLunchFactory().CreateFood().Cook() NewSimpleLunchFactory().CreateVegetable().Cook() } + +func TestTomato_Cook(t *testing.T) { + tests := []struct { + name string + tr *Tomato + }{ + { + name: "测试123", + tr: &Tomato{}, + } + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.tr.Cook() + }) + } +} diff --git a/golang_learn/data_prattern/分类.md b/golang_learn/data_prattern/分类.md new file mode 100644 index 0000000..988891f --- /dev/null +++ b/golang_learn/data_prattern/分类.md @@ -0,0 +1,72 @@ +# GO语言设计模式和成例集锦 + +Go语言从面世就受到了业界的普遍关注,曾有文章分析,Go是最有可能改变未来IT技术的十大语言之一。本文作者列举了Go语言的设计模式和成例合集,并且还进行了详细的分类。 + +## 创建型模式 +* 抽象工厂模式:提供一个接口用于创建相关对象的家族; +* Builder模式:使用简单的对象来构建复杂的对象; +* 工厂方法模式:一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中; +* 对象池模式:实例化并维护一组相同类型的对象实例; +* 单例模式:限制类的实例,保证一个类只有一个实例。 + +## 结构模式 +* 适配器模式:适配另一个不兼容的接口来一起工作; +* 桥接模式:将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化; +* 合成模式:将对象组织到树中,用来描述树的关系; +* 装饰模式:给一个静态或动态对象添加行为; +* 门面(Facade)模式:为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用; +* Flyweight模式:运用共享技术有效地支持大量细粒度的对象; +* MVC模式:是模型(model)-视图(view)-控制器(controller)的缩写,将一个应用程序划分成三个相互关联的部分,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。 +* 代理模式:为其他对象提供一种代理以控制对这个对象的访问。 + +## 行为模式 +* 责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系; +* 命令模式:就是客户端发布一个命令(也就是“请求”),而这个命令已经被封装成一个对象。即这个命令对象的内部可能已经指定了该命令具体由谁负责执行; +* 中介(Mediator)模式:用一个中介对象来封装一系列关于对象交互行为; +* 观察者模式:对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新; +* 注册(Registry)模式:跟踪给定类的所有子类; +* 状态模式:基于一个对象的内部状态,给相同对象提供多种行为; +* 策略模式:定义一系列算法,并将每一个算法封装起来,而且使它们可以相互替换; +* 模板(Template)模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤; +* 访问者模式:表示一个作用于某对象结构中的各元素的操作,它使开发者可以在不改变各元素类的前提下定义作用于这些元素的新操作。 + +## 同步模式 +* 条件变量:利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号); +* Lock/Mutex:执行互斥限制资源获得独占访问; +* 监视器模式:互斥锁和条件变量的组合模式; +* 读写锁定模式:它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作; +* Semaphore:负责协调各个线程,以保证它们能够正确、合理地使用公共资源。 + +## 并行模式 +* Bounded Parallelism:完成大量资源限制的独立任务; +* 广播(Broadcast):把一个消息同时传输到所有接收端; +* 协同(Coroutines):允许在特定地方暂停和继续执行的子程序; +* 生成器:一次性生成一系列值; +* Reactor模式:在事件驱动的应用中,将一个或多个客户的服务请求分离(demultiplex)和调度(dispatch)给应用程序。同步、有序地处理同时接收的多个服务请求。 +* 并行(Parallelism):完成大量的独立任务; +* 生产者消费者:从任务执行中分离任务; +* 调度器(Scheduler):协调任务步骤。 + +## 消息传递模式 +* 扇入(Fan-In):该模块直接调用上级模块的个数,像漏斗型一样去工作; +* 扇出(Fan-Out):该模块直接调用的下级模块的个数; +* Futures & Promises:扮演一个占位角色,对未知的结果用于同步; +* Publish/Subscribe:将信息传递给订阅者; +* Push & Pull:把一个管道上的消息分发给多人。 + +## 稳定模式 +* Bulkheads:实施故障遏制原则,例如防止级联故障; +* 断路器(Circuit-Breaker)模式:当请求有可能失败时,停止流动的请求; +* 截止日期(Deadline):一旦响应变缓,允许客户端停止一个正在等待的响应; +* Fail-Fast机制:集合的一种错误检测机制。当多个线程对集合进行结构上的改变操作时,有可能会产生fail-fast机制; +* Handshaking:如果一个组件的不能访问请求被拒绝,询问是否还能承担更多负载; +* 稳定状态(Steady-State):为每一个服务积累一个资源,其它服务必须回收这些资源; + +## 剖析模式 +* Timing Functions:包装和执行日志的函数; + +## 成例 +* Functional Options:允许给默认值创建clean API和惯用重载; + +## 反模式 +* 级联故障:一个系统的某部分出现错误,与之有关的上下级也随之出现故障,导致多米诺效应。 \ No newline at end of file From 79cc9ebfdd9b08d61e55632b6c39fbfd10494bd7 Mon Sep 17 00:00:00 2001 From: VIVIMAN Date: Sat, 5 Feb 2022 02:13:47 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../abstract_factory/main_test.go | 9 +-- golang_learn/data_prattern/observer/main.go | 59 +++++++++++++++++++ .../data_prattern/observer/main_test.go | 32 ++++++++++ golang_learn/data_prattern/observer/说明.md | 7 +++ 4 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 golang_learn/data_prattern/observer/main_test.go create mode 100644 golang_learn/data_prattern/observer/说明.md diff --git a/golang_learn/data_prattern/abstract_factory/main_test.go b/golang_learn/data_prattern/abstract_factory/main_test.go index 655a188..eb39de5 100644 --- a/golang_learn/data_prattern/abstract_factory/main_test.go +++ b/golang_learn/data_prattern/abstract_factory/main_test.go @@ -1,13 +1,10 @@ package abstract_factory import ( - "reflect" "testing" ) - func TestNewSimpleLunchFactory(t *testing.T) { - NewSimpleLunchFactory().CreateFood().Cook() NewSimpleLunchFactory().CreateVegetable().Cook() } @@ -18,9 +15,9 @@ func TestTomato_Cook(t *testing.T) { tr *Tomato }{ { - name: "测试123", - tr: &Tomato{}, - } + name: "测试123", + tr: &Tomato{}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/golang_learn/data_prattern/observer/main.go b/golang_learn/data_prattern/observer/main.go index 0483094..225846f 100644 --- a/golang_learn/data_prattern/observer/main.go +++ b/golang_learn/data_prattern/observer/main.go @@ -1 +1,60 @@ package observer + +import ( + "sync" + "time" + + "github.com/pingcap/log" +) + +type Event struct { + Data int +} + +type Observer interface { + NotifyCallback(event Event) +} + +type Subject interface { + AddListener(observer Observer) + RemoveListener(observer Observer) + Notity(event Event) +} + +type eventObserver struct { + ID int + Time time.Time +} + +type eventSubject struct { + Observer sync.Map +} + +func (e *eventObserver) NotityCallback(event Event) { + log.Info("输出:%s, 之后输出:%s。", event.Data, time.Since(e.Time)) +} + +func (e *eventSubject) AddListener(observer Observer) { + e.Observer.Store(observer, struct{}{}) +} + +func (e *eventSubject) Notity(event Event) { + e.Observer.Range(func(key, value interface{}) bool { + if key == nil { + return false + } + key.(Observer).NotifyCallback(event) + return true + }) +} + +func Fib(n int) chan int { + c := make(chan int) + go func() { + defer close(c) + for i, j := 0, 1; i < n; i, j = i+j, i { + c <- i + } + }() + return c +} diff --git a/golang_learn/data_prattern/observer/main_test.go b/golang_learn/data_prattern/observer/main_test.go new file mode 100644 index 0000000..74e0d85 --- /dev/null +++ b/golang_learn/data_prattern/observer/main_test.go @@ -0,0 +1,32 @@ +package observer + +import ( + "reflect" + "testing" +) + +func TestFib(t *testing.T) { + type args struct { + n int + } + tests := []struct { + name string + args args + want chan int + }{ + { + name: "测试管道函数-斐波那契数列", + args: args{ + n: 50, + }, + want: make(chan int), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := Fib(tt.args.n); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Fib() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/golang_learn/data_prattern/observer/说明.md b/golang_learn/data_prattern/observer/说明.md new file mode 100644 index 0000000..4c0dcd0 --- /dev/null +++ b/golang_learn/data_prattern/observer/说明.md @@ -0,0 +1,7 @@ + +```go + +``` +* 观察者模式 + +* \ No newline at end of file