• golang设计模式——创建模式



    简介

    设计模式是面向对象软件的设计经验,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。每一种设计模式系统的命名、解释和评价了面向对象中一个重要的和重复出现的设计。

    创建模式是用来帮助我们创建对象的,具体有如下几种:

    1. 工厂模式 (Factory Pattern)
    2. 抽象工厂模式 (Abstract Factory Pattern)
    3. 单例模式 (Singleton Pattern)
    4. 建造者模式 (Builder Pattern)
    5. 原型模式 (Prototype Pattern)

    工厂模式

    通俗解释

    追 MM 少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是 MM 爱吃的东西,虽然口味有所不同,但不管你带 MM 去麦当劳或肯德基,只管向服务员说「来四个鸡翅」就行了。麦当劳和肯德基就是生产鸡翅的 Factory 工厂模式:客户类和工厂类分开。

    消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。

    简单工厂模式

    简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。

    优点

    工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

    缺点

    由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

    代码编写

    由于 Go 本身是没有构造函数的,一般而言我们采用 NewName 的方式创建对象/接口,当它返回的是接口的时候,其实就是简单工厂模式

    package factory
    
    // IRuleConfigParser IRuleConfigParser
    type IRuleConfigParser interface {
       
    	Parse(data []byte)
    }
    
    // jsonRuleConfigParser jsonRuleConfigParser
    type jsonRuleConfigParser struct {
       
    }
    
    // Parse Parse
    func (J jsonRuleConfigParser) Parse(data []byte) {
       
    	panic("implement me")
    }
    
    // yamlRuleConfigParser yamlRuleConfigParser
    type yamlRuleConfigParser struct {
       
    }
    
    // Parse Parse
    func (Y yamlRuleConfigParser) Parse(data []byte) {
       
    	panic("implement me")
    }
    
    // NewIRuleConfigParser NewIRuleConfigParser
    func NewIRuleConfigParser(t string) IRuleConfigParser {
       
    	switch t {
       
    	case "json":
    		return jsonRuleConfigParser{
       }
    	case "yaml":
    		return yamlRuleConfigParser{
       }
    	}
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    单元测试

    package factory
    
    import (
    	"reflect"
    	"testing"
    )
    
    func TestNewIRuleConfigParser(t *testing.T) {
       
    	type args struct {
       
    		t string
    	}
    	tests := []struct {
       
    		name string
    		args args
    		want IRuleConfigParser
    	}{
       
    		{
       
    			name: "json",
    			args: args{
       t: "json"},
    			want: jsonRuleConfigParser{
       },
    		},
    		{
       
    			name: "yaml",
    			args: args{
       t: "yaml"},
    			want: yamlRuleConfigParser{
       },
    		},
    	}
    	for _, tt := range tests {
       
    		t.Run(tt.name, func(t *testing.T) {
       
    			if got := NewIRuleConfigParser(tt.args.t); !reflect.DeepEqual(got, tt.want) {
       
    				t.Errorf("NewIRuleConfigParser() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    工厂模式

    在工厂方法模式中,我们执行单个函数,传入一个参数(提供信息表明我们想要什么),但 并不要求知道任何关于对象如何实现以及对象来自哪里的细节

    适用场景

    创建对象需要大量重复的代码 客户端(应用层)不依赖于产品实例,如何被创建、实现等细节 一个类通过其子类来指定创建哪个对象

    优点

    用户只需要关心所需产品对应的工厂,无须关心创建细节 加入新产品符合开闭原则,提高可扩展性

    缺点

    在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

    代码编写

    当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂

    // IRuleConfigParserFactory 工厂方法接口
    type IRuleConfigParserFactory interface {
       
    	CreateParser() IRuleConfigParser
    }
    
    // yamlRuleConfigParserFactory yamlRuleConfigParser 的工厂类
    type yamlRuleConfigParserFactory struct {
       
    }
    
    // CreateParser CreateParser
    func (y yamlRuleConfigParserFactory) CreateParser() IRuleConfigParser {
       
    	return yamlRuleConfigParser{
       }
    }
    
    // jsonRuleConfigParserFactory jsonRuleConfigParser 的工厂类
    type jsonRuleConfigParserFactory struct {
       
    }
    
    // CreateParser CreateParser
    func (j jsonRuleConfigParserFactory) CreateParser() IRuleConfigParser {
       
    	return jsonRuleConfigParser{
       }
    }
    
    // NewIRuleConfigParserFactory 用一个简单工厂封装工厂方法
    func NewIRuleConfigParserFactory(t string) IRuleConfigParserFactory {
       
    	switch t {
       
    	case "json":
    		return jsonRuleConfigParserFactory{
       }
    	case "yaml":
    		return yamlRuleConfigParserFactory{
       }
    	}
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    单元测试

    package factory
    
    import (
    	"reflect"
    	"testing"
    )
    
    func TestNewIRuleConfigParserFactory(t *testing.T) {
       
    	type args struct {
       
    		t string
    	}
    	tests := []struct {
       
    		name string
    		args args
    		want IRuleConfigParserFactory
    	}{
       
    		{
       
    			name: "json",
    			args: args{
       t: "json"},
    			want: jsonRuleConfigParserFactory{
       },
    		},
    		{
       
    			name: "yaml",
    			args: args{
       t: "yaml"},
    			want: yamlRuleConfigParserFactory{
       },
    		},
    	}
    	for _, tt := range tests {
       
    		t.Run(tt.name, func(t *testing.T) {
       
    			if got := NewIRuleConfigParserFactory(tt.args.t); !reflect.DeepEqual(got, tt.want) {
       
    				t.Errorf("NewIRuleConfigParserFactory() = %v, want %v", got, tt.want)
    			}
    		})
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。一个抽象工厂是一些工厂方法的(逻辑)集合,其中每一个工厂方法负责生成不同的对象。

    通俗解释

    请 MM 去麦当劳吃汉堡,不同的 MM 有不同的口味,要每个都记住是一件烦人的事情,我一般采用 Factory Method 模式,带着 MM 到服务员那儿,说「要一个汉堡」,具体要什么样的汉堡呢,让 MM 直接跟服务员说就行了。

    工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。

    应用环境

    使用工厂模式还是抽象工厂模式?

    通常先从简单的工厂模式开始,后面发现应用程序需要许多的工厂方法,且将这些工厂方法组合起来创建一系列的对象是有意义的,这样的话

  • 相关阅读:
    MUI UI Kit Design System for Figma
    JAVA毕业设计河池市旅游信息系统计算机源码+lw文档+系统+调试部署+数据库
    C++语法基础(1)——编程入门
    微软官方发布的C#开源、免费、实用的Windows工具箱
    Eunomia: 让 ebpf 程序的分发和使用像网页和 web 服务一样自然
    Linux常用网络命令参数整理_incomplete
    优化用户体验:解决element中el-tabs组件切换闪屏问题
    化工供应链如何向产业互联网转型,S2B2C供应链电商系统提升企业供应链效率
    Word控件Spire.Doc 【文本】教程(19) ;如何在 C#、VB.NET 中通过 Word 中的正则表达式查找和替换文本
    kubelets 1.20 证书更新
  • 原文地址:https://blog.csdn.net/qq_39280718/article/details/126681378