diff --git a/.idea/golang-design-patterns.iml b/.idea/golang-design-patterns.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/golang-design-patterns.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..0a86d19
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..dafc2b4
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index f07525b..5198714 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,55 @@
# golang-design-patterns
-使用golang实现各种设计模式
+
+## 使用golang实现各种设计模式
+
+- 创建型模式
+
+ 1. [单例模式]()
+
+ 2. 工厂方法模式
+
+ 3. 抽象工厂模式
+
+ 4. 建造者模式
+
+ 5. 原型模式
+
+- 行为型模式
+
+ 1. 访问者模式
+
+ 2. 模板模式
+
+ 3. 策略模式
+
+ 4. 状态模式
+
+ 5. 观察者模式
+
+ 6. 备忘录模式
+
+ 7. 中介者模式
+
+ 8. 迭代器模式
+
+ 9. 解释器模式
+
+ 10. 命令模式
+
+ 11. 责任链模式
+
+- 结构型模式
+
+ 1. 适配器模式
+
+ 2. 桥接模式
+
+ 3. 组合模式
+
+ 4. 装饰模式
+
+ 5. 外观模式
+
+ 6. 亨元模式
+
+ 7. 代理模式
\ No newline at end of file
diff --git a/singleton/README.md b/singleton/README.md
new file mode 100644
index 0000000..4e14a0f
--- /dev/null
+++ b/singleton/README.md
@@ -0,0 +1,196 @@
+# 单例模式
+
+> wiki百科: 单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
+
+
+单例模式要实现的效果就是,对于应用单例模式的类,整个程序中只存在一个实例化对象
+
+go并不是一种面向对象的语言,所以我们使用结构体来替代
+
+有几种方式:
+
+ - 懒汉模式
+
+ - 饿汉模式
+
+ - 双重检查锁机制
+
+下面拆分讲解:
+
+### 懒汉模式
+
+1. 构建一个示例结构体
+
+ ```go
+ type example struct {
+ name string
+ }
+ ```
+2. 设置一个私有变量作为每次要返回的单例
+
+ ```go
+ var instance *example
+ ```
+
+3. 写一个可以获取单例的方法
+
+ ```go
+ func GetExample() *example {
+
+ // 存在线程安全问题,高并发时有可能创建多个对象
+ if instance == nil {
+ instance = new(example)
+ }
+ return instance
+ }
+ ```
+
+4. 测试一下
+
+ ```go
+ func main() {
+ s := GetExample()
+ s.name = "第一次赋值单例模式"
+ fmt.Println(s.name)
+
+ s2 := GetExample()
+ fmt.Println(s2.name)
+ }
+ ```
+
+懒汉模式存在线程安全问题,在第3步的时候,如果有多个线程同时调用了这个方法,
+那么都会检测到`instance`为`nil`,就会创建多个对象,所以出现了饿汉模式...
+
+
+### 饿汉模式
+
+与懒汉模式类似,不再多说,直接上代码
+
+```go
+
+ // 构建一个结构体,用来实例化单例
+ type example2 struct {
+ name string
+ }
+
+ // 声明一个私有变量,作为单例
+ var instance2 *example2
+
+ // init函数将在包初始化时执行,实例化单例
+ func init() {
+ instance2 = new(example2)
+ instance2.name = "初始化单例模式"
+ }
+
+ func GetInstance2() *example2 {
+ return instance2
+ }
+
+ func main() {
+ s := GetInstance2()
+ fmt.Println(s.name)
+ }
+
+```
+
+饿汉模式将在包加载的时候就创建单例对象,当程序中用不到该对象时,浪费了一部分空间
+
+和懒汉模式相比,更安全,但是会减慢程序启动速度
+
+
+### 双重检查机制
+
+懒汉模式存在线程安全问题,一般我们使用互斥锁来解决有可能出现的数据不一致问题
+
+所以修改上面的`GetInstance()` 方法如下:
+
+```go
+ var mux Sync.Mutex
+ func GetInstance() *example {
+ mux.Lock()
+ defer mux.Unlock()
+ if instance == nil {
+ instance = &example{}
+ }
+ return instance
+ }
+```
+
+如果这样去做,每一次请求单例的时候,都会加锁和减锁,而锁的用处只在于解决对象初始化的时候可能出现的并发问题
+当对象被创建之后,加锁就失去了意义,会拖慢速度,所以我们就引入了双重检查机制(`Check-lock-Check`),
+也叫`DCL`(`Double Check Lock`), 代码如下:
+
+```go
+ func GetInstance() *example {
+ if instance == nil { // 单例没被实例化,才会加锁
+ mux.Lock()
+ defer mux.Unlock()
+ if instance == nil { // 单例没被实例化才会创建
+ instance = &example{}
+ }
+ }
+ return instance
+ }
+```
+
+这样只有当对象未初始化的时候,才会又加锁和减锁的操作
+
+但是又出现了另一个问题:每一次访问都要检查两次,为了解决这个问题,我们可以使用golang标准包中的方法进行原子性操作:
+
+```go
+ import "sync"
+ import "sync/atomic"
+
+ var initialized uint32
+
+ func GetInstance() *example {
+
+ // 一次判断即可返回
+ if atomic.LoadUInt32(&initialized) == 1 {
+ return instance
+ }
+ mux.Lock()
+ defer mux.Unlock()
+ if initialized == 0 {
+ instance = &example{}
+ atomic.StoreUint32(&initialized, 1) // 原子装载
+ }
+ return instance
+ }
+```
+以上代码只需要经过一次判断即可返回单例,但是golang标准包中其实给我们提供了相关的方法:
+
+`sync.Once`的`Do`方法可以实现在程序运行过程中只运行一次其中的回调,所以最终简化的代码如下:
+
+```go
+
+ type example3 struct {
+ name string
+ }
+
+ var instance3 *example3
+ var once sync.Once
+
+ func GetInstance3() *example3 {
+
+ once.Do(func() {
+ instance3 = new(example3)
+ instance3.name = "第一次赋值单例"
+ })
+ return instance3
+ }
+
+ func main() {
+ e1 := GetInstance3()
+ fmt.Println(e1.name)
+
+ e2 := GetInstance3()
+ fmt.Println(e2.name)
+ }
+```
+
+单例模式是开发中经常用到的设计模式,我在制作自己的web框架 [silsuer/bingo](https://github.com/silsuer/bingo) 的时候
+在环境变量控制、配置项控制等位置都用到了这种模式。
+
+想把所有设计模式使用golang实现一遍,开了个新坑[silsuer/golang-design-patterns](https://github.com/silsuer/golang-design-patterns),
+这是第一篇,以后会陆续更新,需要请自取~
\ No newline at end of file
diff --git a/singleton/double-check-lock.go b/singleton/double-check-lock.go
new file mode 100644
index 0000000..2ef57d1
--- /dev/null
+++ b/singleton/double-check-lock.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "sync"
+ "fmt"
+)
+
+/*
+ * 双重锁检查机制
+ */
+
+type example3 struct {
+ name string
+}
+
+var instance3 *example3
+var once sync.Once
+
+func GetInstance3() *example3 {
+
+ once.Do(func() {
+ instance3 = new(example3)
+ instance3.name = "第一次赋值单例"
+ })
+ return instance3
+}
+
+func main() {
+ e1 := GetInstance3()
+ fmt.Println(e1.name)
+
+ e2 := GetInstance3()
+ fmt.Println(e2.name)
+}
diff --git a/singleton/lazy-loading.go b/singleton/lazy-loading.go
new file mode 100644
index 0000000..f203d6d
--- /dev/null
+++ b/singleton/lazy-loading.go
@@ -0,0 +1,35 @@
+package main
+
+import "fmt"
+
+/*
+ * 单例模式之懒汉模式
+ * 非线程安全
+ */
+
+// 首先构造一个结构体
+type example struct {
+ name string
+}
+
+// 设置一个变量作为单例变量,这是一个私有变量,包外不可访问
+var instance *example
+
+// 写一个方法用来返回单例
+func GetExample() *example {
+
+ // 存在线程安全问题,高并发时有可能创建多个对象
+ if instance == nil {
+ instance = new(example)
+ }
+ return instance
+}
+
+func main() {
+ s := GetExample()
+ s.name = "第一次赋值单例模式"
+ fmt.Println(s.name)
+
+ s2 := GetExample()
+ fmt.Println(s2.name)
+}
diff --git a/singleton/starving-loading.go b/singleton/starving-loading.go
new file mode 100644
index 0000000..2bd84a3
--- /dev/null
+++ b/singleton/starving-loading.go
@@ -0,0 +1,31 @@
+package main
+
+import "fmt"
+
+/*
+ * 饿汉模式
+ * 在类加载时就初始化对象
+ */
+
+// 构建一个结构体,用来实例化单例
+type example2 struct {
+ name string
+}
+
+// 声明一个私有变量,作为单例
+var instance2 *example2
+
+// init函数将在包初始化时执行,实例化单例
+func init() {
+ instance2 = new(example2)
+ instance2.name = "初始化单例模式"
+}
+
+func GetInstance2() *example2 {
+ return instance2
+}
+
+func main() {
+ s := GetInstance2()
+ fmt.Println(s.name)
+}