Go 编程模式:Factory 和 Visitor
date
Mar 30, 2023
slug
Go-design-pattern-Factory-Visitor
status
Published
tags
Code
Design Patterns
summary
factory and visitor design patterns
type
Post
Created Time
Oct 28, 2023 01:45 PM
Updated Time
Oct 28, 2023 01:45 PM
AI summary
Status
工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需指定其确切的类。在工厂模式中,创建对象的代码被封装在一个工厂方法中,这个方法可以为客户端代码生成对象。通过使用工厂方法,客户端代码不需要了解每个类的具体实现方式,只需要知道它们实现了相同的接口或抽象类即可。
工厂模式和鸭子类型的理念一致。鸭子是什么?在鸭子类型中,只要一个对象拥有相应的属性,并且实现了相应的方法,就可以被称之为鸭子。同样的,工厂模式里,一个对象,只要实现了对应的方法,就是“工厂”。
代码实现如下:
工厂模式的其中一个优点是增加了类型校验,比如,如果将上面代码中这段代码
删除,编译就会失败,因为
Factory2
没有 asset
方法就不是一个 IFactory
类型了。这样的特性使得客户端代码不需要了解每个类的具体实现方式,只需要知道它们实现了相同的接口或抽象类即可。这意味着,如果将一个对象的实现更改为另一个实现,客户端代码不需要进行任何更改,因为它们只与接口或抽象类进行交互。此外,工厂方法可以使用多态来创建对象,这意味着它可以返回不同的对象,具体取决于运行时的数据类型。工厂模式是一种早期的设计模式,它在软件开发中的实际应用最早可以追溯到上世纪80年代。这种设计模式的主要目的是将对象的创建和使用分离。在不使用工厂模式的情况下,客户端代码通常需要了解每个类的具体实现方式,才能创建对象。这使得客户端代码与具体的类紧密耦合,导致代码难以维护和扩展。而使用工厂模式,客户端代码只需要知道如何使用工厂方法来创建对象,而不需要了解每个类的具体实现方式。这使得客户端代码与具体的类解耦,从而提高了代码的可维护性和可扩展性。
因此,工厂模式被发明的主要目的是为了解决对象创建和使用之间的紧耦合问题,提高代码的可维护性和可扩展性。
访问者模式
访问者模式是一种行为型设计模式,它允许你将算法与作用于某个对象结构的元素的类分离。当一个对象的实际类别对于代码在编译时无法预知时,可以使用访问者模式。
在访问者模式中,我们定义了一个访问者(Visitor),并在访问者中定义了各种访问方法,每个访问方法对应了一个元素类别。元素类别实现了一个叫做“接受”(accept)的方法,这个方法调用访问者中相应的访问方法。这样,我们就可以在不修改元素类别的情况下,定义新的操作。同时,也可以在不修改访问者的情况下,定义新的元素类别。
在代码实现中,可以看到访问者模式的实现是通过将访问者接口定义为 Shape 接口,定义了访问各种形状的访问方法,如 visitForSquare、visitForCircle 和 visitForRectangle 等。不同的访问者可以实现这个接口,然后根据需要实现访问各种元素的方法。
最终,通过调用元素对象的 accept 方法,可以将访问者对象传递给元素对象,然后元素对象就可以调用访问者对象中对应的访问方法来执行特定的操作。这种方式可以使得操作与元素对象解耦,从而提高代码的灵活性和可维护性。
访问者模式可以说是工厂模式的一个拓展。每个工厂都有了对应的方法,但是生产出来的产品却不一样,如何根据不同的工厂,生产出不同的产品呢?
代码实现如下:
最终的输出如下:
代码比较长,我简单解释下。
可以看到,当我们通过
accept
方法访问 areaCalculator
时,根据对象的不同,会返回不同的结果,这是结果。其中
areaCalculator
就是一个工厂类型的实例,这个工厂类型实现了工厂所需要三个方法 visitForSquare
、visitForCircle
和 visitForRectangle
,同样的,还有另一个工厂实例 middleCoordinates
,也实现了相应的三个方法。当不同对象调用 accept
方法时,对象会根据自己的 accept
方法调用“工厂”中实现的方法,这是过程。我在使用中,并不关心过程,只想要一个结果,所以就有了封装。
访问者模式最早可以追溯到上世纪90年代。它是由 Gamma 等人在《设计模式:可复用面向对象软件的基础》一书中首次引入。访问者模式的优点在于它遵循了开放 / 封闭原则,即封装了访问算法,使得可以在不修改元素类别的情况下,定义新的操作。同时,也可以在不修改访问者的情况下,定义新的元素类别。这种方式可以使得操作与元素对象解耦,从而提高代码的灵活性和可维护性。