写点什么

OMG!Go 语言设计模式,这样用简直不要太爽!

  • 2023-03-21
    北京
  • 本文字数:3051 字

    阅读完需:约 10 分钟

【内容概览】


  1. 为什么需要设计模式

  2. 实战示例


1)什么是工厂方法模式


2)工厂方法模式的使用场景


3)工厂方法模式的实现方式


4)Go 语言实战


5)工厂方法模式的优缺点


01

为什么需要设计模式


设计模式可以根据以前的实践和经验记录要采用的解决方案。


在设计模式的实现过程中,需要使用多个软件组件共同实现某些功能。


因此,设计模式加快了涉及多个组件的开发过程。


开发者可以在对应解决方案的具体应用中使用熟悉的编程语言。


例如,如果某个开发者熟悉 Go 语言,那么这个开发者可以使用 Go 语言开发相应的组件。


  • 使用设计模式可以提高开发速度。设计模式提供了经过验证的开发范例,有助于节省时间,而不必在每次出现问题时都重新创建设计模式。

  • 因为设计模式是为了修复已知问题而创建的,所以设计模式可以在软件开发过程中对其进行预测。

  • 使用设计模式可以提高开发者的思维能力、编程能力和设计能力。

  • 设计模式使程序设计更加标准化、代码编制更加工程化,从而提高软件的开发效率,缩短软件的开发周期。

  • 使用设计模式设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。设计模式可以在多种情况下以具体方式使用,可以让系统在后期更容易维护和扩展。


02

实战示例


1)什么是工厂方法模式


工厂方法模式(Factory Method Pattern)定义了一个用于创建对象的接口,但让子类决定实例化哪个类。


接口中的工厂方法允许类将实例化操作推迟到一个或多个具体子类中。


工厂方法模式是创建对象的最佳方法之一,其中的对象创建逻辑对客户端隐藏。


工厂方法模式的 UML 类图如下图所示。



根据上图可知,工厂方法模式的角色组成如下。


  • 工厂(Factory):声明返回产品对象的工厂方法的接口。该方法返回的对象类型必须与产品接口类型相匹配。

  • 具体工厂(ConcreteFactory):实现工厂接口的类,会重写基础工厂方法,使其返回不同类型的产品。

  • 产品(Product):声明产品方法的接口。对于所有由具体工厂类及其子类构建的对象,该接口是通用的。

  • 具体产品(ConcreteProduct):实现产品接口的类。


2)工厂方法模式的使用场景


  • 在程序开发过程中,如果开发者无法预知对象的具体类型及其依赖关系,则可以使用工厂方法模式。工厂方法模式将创建产品的工厂代码与产品代码分离,从而降低代码之间的耦合度。例如,如果需要添加一种新产品,则只需创建一个新的具体工厂类,然后重写其工厂方法。

  • 如果开发者希望其他开发者可以扩展软件库或框架的内部组件,则可以使用工厂方法模式。

  • 如果一个类需要通过子类指定其创建的对象,则可以使用工厂方法模式。


3)工厂方法模式的实现方式


(1)定义工厂接口。


在工厂方法模式中,会在工厂接口中声明对所有产品都有意义的方法,示例代码如下:



(2)定义具体工厂类,并且实现工厂接口中的方法。


示例代码如下:



在具体工厂类的工厂方法中调用具体产品对象,并且返回具体产品对象。开发者可能需要在工厂方法中添加临时参数,用于控制返回的具体产品对象的类型。


(3)定义产品接口,并且定义该接口中的方法签名。


示例代码如下:



(4)定义具体产品类,并且实现产品接口中的方法。


示例代码如下:



(5)创建客户端,使用工厂生产产品。


示例代码如下:



4)Go 语言实战


假设开发者正在开发一款服装工厂的品牌管理应用程序。


该应用程序的最初版本只能生产一种品牌 ANTA 的服装,因此大部分代码都在位于名为 ANTA 的类中。在一段时间后,工厂生产的这个品牌的服装质量很好,销量很高。工厂收到了很多其他公司的合作请求,希望工厂能够生产其他品牌的服装。


在应用程序中新增一个品牌类会遇到问题。如果其他代码与现有的类已经存在耦合关系,那么向应用程序中添加新类会比较麻烦。


目前,大部分代码都与 ANTA 类有关。如果要在应用程序中添加新的品牌类 PEAK,则需要修改之前编写的大部分代码。


此外,如果开发者以后需要在程序中添加其他品牌类,则需要再次对代码进行大规模修改。


使用工厂方法模式可以解决上面的问题。工厂方法模式建议使用特殊的工厂方法调用对象,工厂方法返回的对象通常称为产品。


在工厂方法模式中,开发者可以在子类中重写工厂方法,从而改变其创建的产品类型。


工厂方法模式的 UML 类图如下图所示。



所有产品都必须实现同一个接口。例如,PEAK 类和 ANTA 类都必须实现服装产品接口 IClothes,该接口中声明了方法 GetName()和 GetSize()。只要产品类实现一个共同的产品接口,开发者就可以将其对象传递给客户端,不需要提供其他数据。


客户端不需要了解不同子类返回的对象之间的差别。客户端将所有产品视为抽象的服装产品接口 IClothes。客户端知道所有服装品牌对象都有其相应的方法,无须关心服装品牌对象的具体实现方式。


由于 Go 语言中缺少类和继承等面向对象编程的特性,因此无法使用 Go 语言实现经典的工厂方法模式。不过,开发者仍然可以实现工厂方法模式的基础版本,即简单工厂。在本实战中,开发者会使用服装工厂类生产多种品牌的服装。


首先,创建一个名为 IClothes 的接口,在该接口中定义生产一套服装所需的所有方法;然后,创建实现 IClothes 接口的服装产品类 clothes。


有两种具体的服装产品类,分别是 ANTA 类与 PEAK 类,二者都嵌入了 clothes 类,并且间接实现了 IClothes 接口中的所有方法。


服装工厂类 ClothesFactory 会发挥工厂的作用,即通过传入参数生产所需类型的服装。main.go 文件会扮演客户端的角色,它不会直接与 ANTA 类或 PEAK 类进行互动,而是依靠 ClothesFactory 类创建多种服装产品对象,仅使用字符参数控制生产。


(1)定义服装产品接口 IClothes,该接口中有两个私有方法——setName()和 setSize(),以及两个公共方法——GetName()和 GetSize(),代码如下:



(2)定义服装产品类 clothes 及其方法,该类会被嵌套进 PEAK、ANTA 等具体品牌类,代码如下:



(3)定义具体服装产品类 PEAK 及其初始化函数,代码如下:



(4)定义具体服装产品类 ANTA 及其初始化函数,代码如下:



(5)编写 MakeClothes()函数,该函数会根据实参类型生产不同品牌的服装,代码如下:



(6)创建客户端,测试工厂方法模式,代码如下:



5)工厂方法模式的优缺点


优点:


  • 应用程序的模块具有可扩展性。在工厂方法模式中,调用一个方法与新类的实现是完全分离的。这种情况对如何扩展软件有特殊的影响:工厂方法具有高度的自治性,开发者在添加新类后,无须以任何方式更改应用程序。

  • 工厂组件具有单独可测试性。例如,如果工厂方法模式实现了 3 个类,则可以单独测试每个类的功能。

  • 与类的构造函数或初始化函数不同,可以为工厂方法起一个有意义的名称。


缺点:


  • 系统中类的数量会成对增加,从而提高系统的复杂度。工厂设计模式的实现会导致集成类的数量大幅增加,因为每个具体产品类都需要一个具体工厂类。尽管工厂方法模式有利于软件扩展,但会增加工作量。如果要扩展工厂方法模式的产品系列,则必须调整工厂接口及相应的具体工厂类。因此,针对所需产品类型提前进行可靠规划是必不可少的。

  • 抽象层的引入,提高了开发者对系统的理解难度。在客户端代码中需要使用抽象层,提高了系统的抽象性和开发者的理解难度。


以上节选自《Go 语言设计模式》一书。

以上节选自《Go 语言设计模式》一书。


本书聚焦于 Go 语言设计模式的知识与应用。


全书共 6 章,分别为设计模式入门、创建型设计模式、结构型设计模式、行为型设计模式、设计模式扩展、设计模式与软件架构。


本书简洁而不失技术深度,内容覆盖 Go 语言的主流设计模式和软件架构,以极简的文字介绍了复杂的案例,是学习 Go 语言设计模式和软件架构的实用教程。


该书已经出版发行,并给大家申请到五折优惠,感兴趣的读者朋友欢迎通过如下方式购买。




图片限时五折优惠,快快扫码抢购吧!


图片每日抽奖赠书

奖品《学习的学问》



用户头像

还未添加个人签名 2019-10-21 加入

还未添加个人简介

评论

发布
暂无评论
OMG!Go语言设计模式,这样用简直不要太爽!_博文视点Broadview_InfoQ写作社区