Patrón de diseño de VBA

Método de fábrica del patrón de diseño VBA

Hay 4 relaciones entre objetos:

  1. La relación de agregación
    Inserte la descripción de la imagen aquí
    A tiene una B, por ejemplo, el aeropuerto tiene un avión.

  2. La relación de combinación
    Inserte la descripción de la imagen aquí
     A se compone de B, A contiene B y B es parte de A, se expresa como A tiene B, por ejemplo: el avión tiene un motor.

  3. La relación de herencia
    Inserte la descripción de la imagen aquí
     A deriva de B, B es una especie de A y A es una generalización de B, lo que significa que B es A. Por ejemplo: Boeing 777 es un avión.

  4. La dependencia
    Inserte la descripción de la imagen aquí
     A depende de B, y A usa B, se expresa como A usa a B. Por ejemplo: avión usa un piloto.

Mecanismo orientado a objetos de VBA

 En VBA, no hay un mecanismo de herencia, pero no importa, porque puede usar la composición para compensar. La clave de la programación orientada a objetos es la clase, porque la clase es el plano del objeto, que es la clave de la programación orientada a objetos.

Cuatro características del título orientado a objetos: (POO)

  1. Abstracción Abstracción
     Escribir código es en realidad un proceso abstracto, cuyas funciones abstraen una serie de operaciones ejecutables. Un módulo abstrae un conjunto de operaciones relacionadas, una clase abstrae un conjunto de datos y operaciones relacionadas, e incluso las variables son una abstracción.
     El código claramente estructurado opera en un solo nivel abstracto y llama a otras funciones encapsuladas En un nivel superior, no nos preocupan los detalles de implementación subyacentes.
     La clase es una abstracción importante: la clase define la plantilla del objeto, y el objeto encapsula los datos y publica los métodos para operar los datos.
  2. Encapsulación La encapsulación
     es similar a la abstracción: encapsula los detalles de implementación y solo publica la interfaz para uso externo. Las variables globales son lo opuesto a la encapsulación. Si hay un campo público en el módulo de clase, no está encapsulando sus datos. No es necesario exponer campos en programación, sino exponer atributos. Los descriptores de acceso a atributos pueden contener código lógico, que es la belleza de la encapsulación.
  3. Polimorfismo
     Si nunca antes ha utilizado una interfaz, es difícil entender el polimorfismo. La interfaz permite que VBA abra la puerta a la programación orientada a objetos. Los objetos tienen múltiples formas de habilidades, llamadas polimorfismo.
  4. Herencia
     VBA no tiene un mecanismo de herencia. Una clase tiene la capacidad de heredar miembros de otra clase. Cuando dos clases están relacionadas de una manera is-a, la herencia funciona. La herencia es uno de los cuatro pilares de OPP, pero la combinación no lo es. La interfaz VBA es una clase con miembros vacíos.

combinación

 En VBA, la relación entre clases no es es-a, sino algo que esta clase tiene-a. Cuando un objeto encapsula instancias de otros objetos, hace uso de grupos. Es posible encapsular objetos externos y exponerlos para simular completamente la herencia de clases.

Propósito de la encapsulación

 De forma predeterminada, las clases de VBA son privadas y solo se pueden usar en el proyecto donde están definidas. Las propiedades del módulo de clase también se pueden configurar como "PublicNotCreatable" y usarse en otros proyectos. Otros proyectos agregarán este proyecto VBA como referencia (como hacer referencia a una biblioteca de scripts, ahora haciendo referencia a otro .xlsm o .xlam). En el proyecto de VBA al que se hace referencia, puede ver y usar las clases en otros proyectos a los que se hace referencia, pero no puede crear sus instancias. Se necesita una forma de exponer la funcionalidad al proyecto de VBA al que se hace referencia para devolver una instancia de la clase pública.

Modo de columna única singleton

 En el patrón de diseño OOP, el método de fábrica se usa generalmente en combinación con el patrón de una sola columna, porque la clase de fábrica solo necesita tener una instancia. Si el cliente no puede usar la palabra clave New para crear una instancia de clase, establecer la propiedad VB_PredeclaredId en True esencialmente hace que la instancia predeterminada de la clase sea un singleton válido.

Instancia predeterminada en VBA

 Primero exporte un módulo de clase VBA, luego ábralo con el Bloc de notas, verá las siguientes propiedades:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "类1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True

 En el módulo de formulario de VBA, hay una instancia predeterminada, debido a que el atributo se establece en Verdadero en el módulo de formulario, este atributo de VBA crea automáticamente un objeto de alcance global. Exporte el módulo de formulario de la misma manera y ábralo con el Bloc de notas.

VERSION 5.00
Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} UserForm1 
   Caption         =   "UserForm1"
   ClientHeight    =   3015
   ClientLeft      =   120
   ClientTop       =   465
   ClientWidth     =   4560
   OleObjectBlob   =   "UserForm1.frx":0000
   StartUpPosition =   1  '所有者中心
End
Attribute VB_Name = "UserForm1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True '该属性是打开VBA面向对象编程的关键
Attribute VB_Exposed = False

 Puede usar UserForm1.Show directamente al mostrar el formulario. La instancia de UserForm1 creada no se muestra y se usa una instancia existente. Porque crea automáticamente un objeto global predeterminado con el nombre de la clase, al igual que una clase estática.
 Use la instancia predeterminada como el modo de una sola columna en VBA, este atributo es la clave para abrir la programación de VBA OOP. Con este atributo, podemos tener un objeto de solo lectura válido en VBA.

ejemplo

 Si tiene una clase de automóvil, hay tres atributos de marca, modelo y fabricante en la clase, a saber, tiempo de fabricación, modelo de automóvil y fabricante.

'@Folder("VBAProject")
'@Class Car
Option Explicit
Private Type TCar
    Make As Long
    Model As String
    Manufacturer As String
End Type

Private this As TCar

Public Property Get Make() As Long
    Make = this.Make
End Property

Friend Property Let Make(ByVal Value As Long)
    this.Make = Value
End Property

Public Property Get Model() As String
    Model = this.Model
End Property

Friend Property Let Model(ByVal Value As String)
    this.Model = Value
End Property

Public Property Get Manufacturer() As String
    Manufacturer = this.Manufacturer
End Property

Friend Property Let Manufacturer(ByVal Value As String)
    this.Manufacturer = Value
End Property

 La palabra clave Friend pasa a ser de solo lectura para los elementos de referencia externa. La clase CarFactory definida en el mismo proyecto puede acceder a los datos modificados por Friend.

'@Exposed
'@Folder("VBAProject")
'@PredeclaredId=True
'@ClassName CarFactory
Option Explicit
Public Function Create(ByVal carMake As Long, ByVal carModel As String, ByVal carManufacturer As String) As Car
    Dim result As Car
    Set result = New Car
    With New result
        .Make = carMake
        .Model = carModel
        .Manufacturer = carManufacturer
    End With
    Set Create = result
End Function

 La función PredeclaredId de CarFactory se establece en True, y el código de cliente VBA puede llamar a esta clase de esta manera.

Public Sub DoSomething()
    Dim myCar  As Car
    Set myCar = CarFactory.Create(2020, "Civic", "Honda")
Debug.Print "We hav a " & myCar.Make & " " & myCar.Manufacturer & " " & myCar.Model & " here."
End Sub

Interfaz en VBA

 En VBA, los miembros públicos de un módulo de clase definen la interfaz predeterminada de la instancia de clase. En teoría, cualquier otra clase puede implementar la interfaz predeterminada de cualquier otra clase. En la práctica, los módulos de clase se utilizan para definir interfaces abstractas formales (solo códigos auxiliares de métodos sin implementación), y estas clases especiales se denominan interfaces.
 Por ejemplo, agregue un módulo de clase y utilícelo como una interfaz denominada ICar.

'@Interface
'@Folder("VBAProject")
'@ClassName ICar
Option Explicit
Public Property Get Make() As Long
End Property
 
Public Property Get Model() As String
End Property
 
Public Property Get Manufacturer() As String
End Property

Implementar interfaz en VBA

 En VBA, la palabra clave Implements se usa en la parte de declaración del módulo de clase para decirle al compilador que la clase se puede usar con una interfaz específica. Pero cada miembro de la interfaz debe implementarse y se producirán errores de compilación si no se implementan.
 Por lo tanto, el código anterior tiene una interfaz abstracta ICar. Indica que cualquier objeto que implemente esta interfaz tiene atributos de solo lectura Marca, Modelo y Fabricación.

'@Folder("VBAProject")
'@PredeclaredId
'@ClassName ReadOnlyCar
Option Explicit

Implements ICar

Private Type TCar
    Make As Long
    Model As String
    Manufacture As String
End Type
Private this As TCar

Private Property Get ICar_Make() As Long
   ICar_Make = this.Make
End Property

Private Property Get ICar_Model() As String
    ICar_Model = this.Model
End Property

Private Property Get ICar_Manufacturer() As String
    ICar_Manufacturer = this.Manufacture
End Property

 Tenga en cuenta que el código de implementación es siempre privado y no se puede cambiar. Estos métodos no son públicos en instancias de clases. Solo se puede acceder a estos métodos a través de ICar.
 Moví el método Create de la clase de fábrica a la propia clase ReadOnlyCar y la función devuelve la interfaz ICar

Public Function Create(ByVal carMake As Long, ByVal carModel As String, ByVal carManufacturer As String) As ICar
    With this
        .Make = carMake
        .Model = carModel
        .Manufacturer = carManufacturer
    End With
    Set Create = Me
End Function

 Debido a que la propiedad VB_PredeclaredId de la clase está establecida en True, obtendrá una instancia predeterminada global gratuita. El código de cliente se puede utilizar así.

Dim myCar as ICar
set myCar=ReadOnlyCar.Create(2020,"Honda","Fit")
'在这里mycar只能访问ICar的成员。

 Es muy problemático para cada clase de implementación proporcionar los métodos anteriores. Redefinir una interfaz de fábrica abstracta ICarFactory.

'@Folder("VBAProject")
'@Interface
Option Explicit

Public Function Create(ByVal carMake As Long, ByVal carModel As String, ByVal carManufacturer) As ICar

End Function

 ICar implementa esta interfaz, el código se simplifica y el método Create original se elimina. el código se muestra a continuación:

'@Folder("VBAProject")
'@Class Car
Option Explicit
Implements ICar
Implements IFactory
Private Type TCar
    Make As Long
    Model As String
    Manufacturer As String
End Type

Private this As TCar

Public Property Get Self() As IFactory
	Set Self = Me
End Property


Private Property Get ICar_Make() As Long
    'TODO implement interface member
    ICar_Make = this.Make
End Property

Private Property Get ICar_Model() As String
    'TODO implement interface member
    ICar_Model = this.Model
End Property

Private Property Get ICar_Manufacturer() As String
    'TODO implement interface member
    ICar_Manufacturer = this.Manufacturer
End Property

Private Function IFactory_Create(ByVal carMake As Long, ByVal carModel As String, ByVal carManufacturer As Variant) As ICar
   With this
        .Make = carMake
        .Model = carModel
        .Manufacturer = carManufacturer
    End With
    Set IFactory_Create = Me
End Function

 El código del cliente se implementa de la siguiente manera, que se vuelve muy conciso.

Public Sub main()
    Dim myCar As ICar
    Set myCar = ReadOnlyCar.Self.Create(2020, "丰田", "上汽")
    Debug.Print myCar.Make, myCar.Manufacturer, myCar.Model
End Sub

 Lo anterior es el método de fábrica implementado en VBA, que puede implementar operaciones de inicialización de objetos VBA y simular constructores de lenguaje de alto nivel.

Definición de método de fábrica

 Defina una interfaz para crear objetos y deje que la subclase decida qué clase instanciar. Los métodos de fábrica retrasan la instanciación de una clase a sus subclases.
Diagrama de clases general del patrón del método de fábrica

Inserte la descripción de la imagen aquí
 En el patrón del método de fábrica, la clase de producto abstracto Product es responsable de definir la similitud de los productos y realizar la definición abstracta más alta de las cosas; Creator es una clase de creación abstracta, es decir, una fábrica abstracta. Cómo crear una clase de producto está hecho por la fábrica de realización de hormigón ConcreteCreateor.
 Tomemos como ejemplo la historia de la creación de seres humanos por parte de Nuwa:
Inserte la descripción de la imagen aquí
según el color de la piel, cree personas de protección de diferentes colores.
El primer paso: de
 acuerdo con la semántica del método de fábrica, primero se encuentra lo común de los seres humanos. El color de la piel humana y las diferentes sílabas del habla se abstraen y publican como una interfaz.

'@Interface IHuman
Publci Sub getColor()
'皮肤颜色不同
End sub
public Sub talk()
'说法方式不同
End sub
'@不同护色的人实现该接口
'@YelloHuman
Implements IHuman
Private Sub IHuman_getColor()
    Debug.Print "黄色人种的皮肤颜色是黄色的!"
End Sub

Private Sub IHuman_talk()
    Debug.Print "黄色人种会说话,一般说的都是双字节。"
End Sub
'@WhiteHuman
Private Sub IHuman_getColor()
    Debug.Print "白色人种的皮肤颜色是白色的!"
End Sub

Private Sub IHuman_talk()
    Debug.Print "白色人种会说话,一般都是单字节。"
End Sub
'@BlackHuman
Private Sub IHuman_getColor()
	Debug.Print "黑色人种的皮肤颜色是黑色的!"
End Sub

Private Sub IHuman_talk()
	Debug.Print "黑人会说话,一般听不懂"
End Sub

 El código VBA anterior ha completado la definición de la parte más abstracta de las cosas según la semántica del método de fábrica.

'@Interface IAbstractFactory
public Function CreateObject(Value as IHuman) as IHuman
'通过接口来延迟到子类实例化对象
End Function
'AbstactFactory
Implements AbstactHumanFactory

Public Property Get Self() As IAbstactFactory
    Set Self = Me
End Property

Private Function AbstactFactory_CreateOject(Value As IHuman) As IHuman
    Set AbstactFactory_CreateOject = Value
End Function

Supongo que te gusta

Origin blog.csdn.net/qq_25686631/article/details/109712071
Recomendado
Clasificación