1、策略模式
(1)什么是策略模式?
策略模式是指对象的某个行为在不同的场景中,拥有不同的实现策略。
策略模式属于行为型模式,策略模式的本质其实就是面向对象中多态的思想。
(2)生活场景实例
小明的班级决定为期中考试成绩优异的同学颁发奖品。奖品一共有钢笔、篮球、本子、手表四种,每位同学可以自己选择想要哪一种类型的奖品。
不使用策略模式(即不使用多态):
package main
type Student interface {
selectThePen(*pen)
selectTheBasketball(*basketball)
selectTheNotebook(*notebook)
selectTheWatch(*watch)
}
type student struct {
name string
}
func (s *student) selectThePen(p *pen) {
fmt.Println(s.name, "选择了奖品:", p.Name())
}
func (s *student) selectTheBasketball(b *basketball) {
fmt.Println(s.name, "选择了奖品:", b.Name())
}
func (s *student) selectTheNotebook(n *notebook) {
fmt.Println(s.name, "选择了奖品:", n.Name())
}
func (s *student) selectTheWatch(w *watch) {
fmt.Println(s.name, "选择了奖品:", w.Name())
}
type pen struct {}
func (p *pen) Name() string {
return "钢笔"
}
type basketball struct {}
func (b *basketball) Name() string {
return "篮球"
}
type notebook struct {}
func (n *notebook) Name() string {
return "本子"
}
type watch struct {}
func (w *watch) Name() string {
return "手表"
}
func main() {
xiaowang := &student {
name : "小王"
}
xiaowang.selectThePen(&pen{})
xiaohong := &student {
name : "小红"
}
xiaohong.selectTheNotebook(¬ebook{})
xiaoming := &student {
name : "小明"
}
xiaoming.selectTheBasketball(&basketball{})
}
策略模式实现(使用多态):
package main
type Student interface {
selectThePrize(Prize)
}
type Prize interface {
Name() string
}
type student struct {
name string
}
func (s *student) selectThePrize(p Prize) {
fmt.Println(s.name, "选择了奖品:", p.Name())
}
type pen struct {}
func (p *pen) Name() string {
return "钢笔"
}
type basketball struct {}
func (b *basketball) Name() string {
return "篮球"
}
type notebook struct {}
func (n *notebook) Name() string {
return "本子"
}
type watch struct {}
func (w *watch) Name() string {
return "手表"
}
func main() {
xiaowang := &student {
name : "小王"
}
xiaowang.selectThePrize(&pen{})
xiaohong := &student {
name : "小红"
}
xiaohong.selectThePrize(¬ebook{})
xiaoming := &student {
name : "小明"
}
xiaoming.selectThePrize(&basketball{})
xiaohua := &student {
name : "小花"
}
xiaohua.selectThePrize(&watch{})
}
(3)etcd interval_tree中的应用
type Comparable interface {
// Compare gives the result of a 3-way comparison
// a.Compare(b) = 1 => a > b
// a.Compare(b) = 0 => a == b
// a.Compare(b) = -1 => a < b
Compare(c Comparable) int
}
2、代理模式
(1)什么是代理模式?
代理模式为其他对象提供一种代理以控制对这个对象的访问。
代理模式属于结构型模式。在某些情况下,一个对象不适合或者不能直接引用另一个对象,代理模式引入一个代理对象,通过代理对象实现对原对象的引用。代理模式的使用场景非常广泛,包括权限控制、数据库连接等。
代理分为静态代理和动态代理。
(2)生活场景实例
在小明的班级,任课老师每天都会布置家庭作业,同学们写完后,第二天统一上交给老师。
package main
import "fmt"
type Student interface {
HandleInHomework(*teacher)
}
type Teacher interface {
CollectHomework(string)
}
type student struct {
name string
}
func (s *student) HandleInHomework(t *teacher) {
fmt.Println(s.name, "交作业给", t.name)
t.CollectHomework(s.name)
}
type teacher struct {
name string
}
func (t *teacher) CollectHomework(name string) {
fmt.Println(t.name, "收到了", name, "的作业")
}
func main() {
zhangsan := &student {
name : "张三",
}
t := &teacher {
name : "语文老师",
}
zhangsan.HandleInHomework(t)
}
语文老师同时教了5个班级,没记全每个班的人数和同学的名字,但是他需要知道每个班级哪些同学没交作业。于是语文老师在每个班级都选了一个语文课代表出来,由语文课代表统一收集班级作业,统计没交作业的学生名单。这里语文课代表就是代理。
package main
import "fmt"
type Student interface {
HandleInHomework(*teacher)
}
type Teacher interface {
CollectHomework(string)
}
type student struct {
name string
}
func (s *student) HandleInHomework(a *assistant) {
fmt.Println(s.name, "交作业给", a.name)
a.CollectHomework(s.name)
}
type teacher struct {
name string
}
func (t *teacher) CollectHomework(name string) {
fmt.Println(t.name, "收到了", name, "的作业")
}
type assistant struct {
name string
t *teacher
}
func (a *assistant) CollectHomework(name string) {
fmt.Println(a.name, "收到了", name, "的作业")
fmt.Println(a.name, "统计谁交了作业")
a.t.CollectHomework(name)
}
func main() {
zhangsan := &student {
name : "张三",
}
t := &teacher {
name : "语文老师",
}
a := &assistant {
name : "语文课代表",
t : t,
}
zhangsan.HandleInHomework(a)
}
(3)代理模式的特点
1)代理类和被代理类具有相同的父类(实现了相同的接口)。
2)代理类保存了一个被代理类的引用。
3)代理类接受所有调用端的请求,并且这些请求最终都会返回给被代理类。
(4)动态代理
type Teacher interface {
collectHomework(string)
}
定义了接口Teacher,不去定义实现类,运行时自动生成实现了collectHomework接口的一个实例。
(5)etcd auth中的应用
type AuthProxy struct {
client *clientv3.Client
}
func (ap *AuthProxy) AuthEnable(ctx context.Context, r *pb.AuthEnableRequest)(*pb.AuthEnableResponse, error) {
conn := ap.client.ActiveConnection()
return pb.NewAuthClient(conn).AuthEnable(ctx, r)
}
3、建造者模式
(1)什么是建造者模式?
建造者模式是指将一个复杂对象的创建和它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一种创建型模式,当一个对象的属性过于复杂时,我们可以把对象实例化的过程进行拆分成多个步骤,每个步骤负责初始化不同的属性。
(2)生活场景实例
新学期开学,小明的学校会进行分班,每个班级由班主任进行组建。班主任为了方便管理,为小明的班级选出若干班干部,包括班长、学习委员、语文课代表、数学课代表和英语课代表。
package main
import "fmt"
type class struct {
monitor string
studentAssistant string
chineseAssistant string
mathAssistant string
englishAssistant string
}
func main() {
c := &class {
monitor : "小明",
studentAssistant : "小红",
}
fmt.Printf("班长:%s,学习委员:%s", c.monitor, c.studentAssistant)
}
小明的班级班长竞选规则采取自主报名,由班级同学投票的方式进行选出。学习委员的竞选规则采取自主报名,由班主任指定担任。
package main
import "fmt"
type class struct {
monitor string
studentAssistant string
chineseAssistant string
mathAssistant string
englishAssistant string
}
func (c *class) setMonitor(monitor string){
fmt.Println("自主报名...")
fmt.Println("班级同学投票...")
fmt.Println("统计票数,得出结果...")
c.monitor = monitor
}
func (c *class) setStudentAssistant(studentAssistant string){
fmt.Println("自主报名...")
fmt.Println("老师直接指定...")
c.studentAssistant = studentAssistant
}
func main() {
c := &class {}
c.setMonitor("小明")
c.setStudentAssistant("小红")
fmt.Printf("班长:%s,学习委员:%s", c.monitor, c.studentAssistant)
}
当B班级也要进行选举时,用建造者模式代码如下:
package main
import "fmt"
type class interface{
build() class
}
type classA struct {
monitor string
studentAssistant string
chineseAssistant string
mathAssistant string
englishAssistant string
}
type classB struct {
monitor string
studentAssistant string
chineseAssistant string
mathAssistant string
englishAssistant string
}
type ClassBuilder interface {
buildMonitor(string) ClassBuilder
buildStudentAssistant(string) ClassBuilder
buildChineseAssistant(string) ClassBuilder
buildMathAssistant(string) ClassBuilder
buildEnglishAssistant(string) ClassBuilder
build() class
}
func (c *classA) buildMonitor(monitor string) ClassBuilder {
fmt.Println("自主报名...")
fmt.Println("班级同学投票...")
fmt.Println("统计票数,得出结果...")
c.monitor = monitor
return c
}
func (c *classB) buildMonitor(monitor string) ClassBuilder {
fmt.Println("自主报名...")
fmt.Println("任课老师和班主任共同指定...")
c.monitor = monitor
return c
}
func (c *classA) buildStudentAssistant(studentAssistant string) ClassBuilder {
fmt.Println("自主报名...")
fmt.Println("老师指定,得出结果...")
c.studentAssistant = studentAssistant
return c
}
func (c *classB) buildStudentAssistant(studentAssistant string) ClassBuilder {
fmt.Println("自主报名...")
fmt.Println("老师指定,得出结果...")
c.studentAssistant = studentAssistant
return c
}
func (c *classA) buildChineseAssistant(chineseAssistant string) ClassBuilder {
c.chineseAssistant = chineseAssistant
return c
}
func (c *classB) buildChineseAssistant(chineseAssistant string) ClassBuilder {
c.chineseAssistant = chineseAssistant
return c
}
func (c *classA) buildMathAssistant(mathAssistant string) ClassBuilder {
c.mathAssistant = mathAssistant
return c
}
func (c *classB) buildMathAssistant(mathAssistant string) ClassBuilder {
c.mathAssistant = mathAssistant
return c
}
func (c *classA) buildEnglishAssistant(englishAssistant string) ClassBuilder {
c.englishAssistant = englishAssistant
return c
}
func (c *classB) buildEnglishAssistant(englishAssistant string) ClassBuilder {
c.englishAssistant = englishAssistant
return c
}
func (c *classA) build() class {
return c
}
func (c *classB) build() class {
c.buildMonitor("小张").buildStudentAssistant("小吴")
return c
}
func main() {
c := &classA{}
c.buildMonitor("小明").buildStudentAssistant("小红")
fmt.Printf("A班级,班长:%s,学习委员:%s\n", c.monitor, c.studentAssistant)
b := &classB{}
b.build()
fmt.Printf("B班级,班长:%s,学习委员:%s\n", b.monitor, b.studentAssistant)
}
(3)建造者模式的特点
1)属性的初始化过程互相独立,易扩展。
2)内部变化复杂的情况下会产生很多建造类。
(4)BeegoHTTPRequest中的应用
func (b *BeegoHTTPRequest) SetBasicAuth(username, password string) *BeegoHTTPRequest {
b.req.SetBasicAuth(username, password)
return b
}
// SetEnableCookie sets enable/disable cookiejar
func (b *BeegoHTTPRequest) SetEnableCookie(enable bool) *BeegoHTTPRequest {
b.setting.EnableCookie = enable
return b
}
// SetUserAgent sets User-Agent header field
func (b *BeegoHTTPRequest) SetUserAgent(useragent string) *BeegoHTTPRequest {
b.setting.UserAgent = useragent
return b
}
4、模板方法模式
(1)什么是模板方法模式?
模板方法模式定义一个算法的步骤,并允许子类为一个或多个步骤提供其具体实现。
模板方法模式属于行为型模式,其本质无非就是利用了里氏替换原则(所有使用父类的地方都可以用子类替代,子类可以扩展父类的功能,但不能改变父类的功能),也是面向对象多态思想的体现。
(2)生活场景实例
每周一到周五,小明都要去上学,小明上学的一天基本都是固定的,去学校、晨读、上课、下课、放学。今天是星期一,小明去学校上学了。
package main
import "fmt"
type Student interface {
SchoolDay()
}
type student struct {
name string
}
func (s *student) GoToSchool() {
fmt.Println(s.name, "去学校")
}
func (s *student) MorningReading() {
fmt.Println(s.name, "晨读")
}
func (s *student) TakingClasses() {
fmt.Println(s.name, "上课")
}
func (s *student) ClassesOver() {
fmt.Println(s.name, "下课")
}
func (s *student) SchoolOver() {
fmt.Println(s.name, "放学")
}
func (s *student) SchoolDay() {
s.GoToSchool()
s.MorningReading()
s.TakingClasses()
s.ClassesOver()
s.SchoolOver()
}
func main() {
s := &student{
name : "小明"
}
s.SchoolDay()
}
小张跟小明是同班同学,小张学习非常努力,上课期间除了学习学校的课程之外,还会用课余时间进行补习。
package main
import "fmt"
type Student interface {
SchoolDay()
}
type xiaoming struct {
template
name string
}
type xiaozhang struct {
template
name string
}
func (xiaozhang *xiaozhang) TakingClasses() { // 子类的方法覆盖模板父类的方法
fmt.Println(xiaozhang.name, "上课")
fmt.Println(xiaozhang.name, "补习")
}
type Template interface {
GoToSchool()
MorningReading()
TakingClasses()
ClassesOver()
SchoolOver()
}
type template struct {
name string
}
func (s *template) GoToSchool() {
fmt.Println(s.name, "去学校")
}
func (s *template) MorningReading() {
fmt.Println(s.name, "晨读")
}
func (s *template) TakingClasses() {
fmt.Println(s.name, "上课")
}
func (s *template) ClassesOver() {
fmt.Println(s.name, "下课")
}
func (s *template) SchoolOver() {
fmt.Println(s.name, "放学")
}
func (s *template) SetName(name string){
s.name = name
}
func SchoolDay(s Template) {
s.GoToSchool()
s.MorningReading()
s.TakingClasses()
s.ClassesOver()
s.SchoolOver()
}
func main() {
xiaoming := &xiaoming{
name : "小明"
}
xiaoming.SetName(xiaoming.name)
SchoolDay(xiaoming)
xiaozhang := &xiaozhang{
name : "小张"
}
xiaozhang.SetName(xiaozhang.name)
SchoolDay(xiaozhang)
}
(3)模板方法的特点
1)提高了代码的复用性。
2)提高了拓展性。
3)缺点:每一种算法的实现都需要新增一个子类,导致了子类个数的增加,增加了系统实现的复杂度。
(4)go-micro service中的应用
type Service interface{
Init(...Option)
Option() Options
Client() client.Client
Server() server.Server
Run() error
String() string
}
// Function is a one time executing Service
type Function interface {
// Inherits Service interface
Service
// Done signals to complete execution
Done() error
// Handle registers an RPC handler
Handle(v interface{}) error
// Subscribe registers a subscriber
Subscribe(topic string, v interface{}) error
}
(5)go http包中的应用
// Handle registers the handler for the given pattern in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) {
DefaultServeMux.Handle(pattern, handler)
}
// HandleFunc registers the handler function for the given pattern in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}