Это очень хороший вопрос по design-patterns
с VBA
.
Полное описание strategy pattern
можно увидеть здесь , но, резюмируя, это класс UML и диаграмма последовательности, описывающая его:
По сути, эта стратегия позволяет алгоритму варьироваться независимо от клиентов, которые его используют.
Откладывание решения о том, какой алгоритм использовать до времени выполнения, позволяет вызывающему коду быть более гибким и многократно используемым.
Вы предложили эти два решения, и я хочу объяснить, почему я их не использовал:
- Обтекание
DatabaseStrategy
вокруг записи, относящейся к записи и приложению (DatabaseStrategy.Create(Record).Save
)
Использование этого решения уменьшит сплоченность , поскольку class
DatabaseStrategy придется позаботиться о создании экземпляра Record
objects
(что, как я покажу позже, это можно сделать, применив Factory-Pattern
)
- Представление
DatabaseStrategy
в качестве члена Записи, но затем кажется, что приложение должно знать, что DatabaseStrategy
является членом записи (Record.DatabaseStrategy.Save
)
Этот шаблон проектирования ДОЛЖЕН знать стратегию, но новшеством является то, что он может быть изменен во время выполнения, передавая объект требуемой стратегии, который реализует методы действия. В этом случае я бы отодвинул DatabaseStrategy
от Record
, потому что последнее упомянутое - это object
, которое нужно сохранить, но не агент выполняет действие (которое может быть Database
class
как я покажу позже).
Чтобы решить проблему создания экземпляра objects
с помощью конструкторов VBA class
, которые не принимают аргументы, я использовал другой шаблон: Factory Pattern .
Приведенный ниже код написан просто для иллюстрации того, как использовать эти два шаблона, поэтому многие функции опущены, и нет реальной реализации методов базы данных. Теперь вот остаток кода:
IRecord class
( Интерфейс ):
Public Function getValue() As String: End Function
Public Function setValue(stringValue As String): End Function
Запись class
:
Этот класс в основном представляет запись базы данных. Для простоты у нас есть только свойство value
, но реальная реализация, конечно, будет другой.
Implements IRecord
Private value As String
Private Function IRecord_getValue() As String
IRecord_getValue = value
End Function
Private Function IRecord_setValue(stringValue As String)
value = stringValue
End Function
IConnectionStrategy class
( Интерфейс )
Это стратегия интерфейса соединения. Здесь мало что изменилось из вашего кода.
Public Function Save(ByVal record As IRecord): End Function
ConnectionStrategyA class
Класс для стратегии А. Здесь мало что изменилось из вашего кода.
Implements IConnectionStrategy
Private connectionString As String
Private Sub Class_Initialize()
connectionString = "DRIVER=Oracle Server;SERVER=myA.server.com\DatabaseA;"
End Sub
'Implements Strayegy A
Private Function IConnectionStrategy_Save(ByVal record As IRecord)
Debug.Print "Saving to ", connectionString, "Record with value:", record.getValue
End Function
ConnectionStrategyB class
Класс для стратегии А. Здесь мало что изменилось из вашего кода.
Implements IConnectionStrategy
Private connectionString As String
Private Sub Class_Initialize()
connectionString = "DRIVER=SQL Server;SERVER=myB.server.com\DatabaseB;"
End Sub
'Implements Strategy B
Private Function IConnectionStrategy_Save(ByVal record As IRecord)
Debug.Print "Saving to ", connectionString, "Record with value:", record.getValue
End Function
База данных class
Это класс, который обрабатывает соединение с базой данных. Стратегия подключения определяет, как подключиться к базе данных.
Обратите внимание, что вы можете изменить стратегию без необходимости переделывать объект, просто вызовите setConnectionStrategy(...)
Private connection As IConnectionStrategy
Private Sub Class_Initialize()
'Initialize everything but strategy.
End Sub
'Funzione che verrà richiamata per inizializzare le propietà della classe
Public Sub InitiateProperties(ByVal connectionStrategy As IConnectionStrategy)
Set connection = connectionStrategy
End Sub
Public Sub saveRecord(ByVal record As IRecord)
connection.Save record
End Sub
Public Sub setConnectionStrategy(ByVal strategy As IConnectionStrategy)
connection = strategy
End Sub
Private Sub Class_Terminate()
'close connections
End Sub
DatabaseFactory Module
(VBA не имеет статического класса, поэтому используйте вместо него модуль)
Этот класс отвечает за создание вашей Database Objects
'Instantiate a Database with given Strategy
Public Function createDatabaseWithStrategy(strategy As IConnectionStrategy) As Database
Set createDatabaseWithStrategy = New Database
CreateFoglioIdro.InitiateProperties connectionStrategy:=strategy
End Function
'Instantiate a Database with Strategy A
Public Function createDatabaseWithStrategyA() As Database
Set createDatabaseWithStrategyA = New Database
createDatabaseWithStrategyA.InitiateProperties connectionStrategy:=New ConnectionStrategyA
End Function
'Instantiate a Database with Strategy B
Public Function createDatabaseWithStrategyB() As Database
Set createDatabaseWithStrategyB = New Database
createDatabaseWithStrategyB.InitiateProperties connectionStrategy:=New ConnectionStrategyB
End Function
И, наконец, пример приложения (App Module
):
Option Explicit
Public Sub ApplicationA()
Dim record As IRecord
Set record = New record
record.setValue ("This is a value")
Dim db As Database
Set db = DatabaseFactory.createDatabaseWithStrategyA
db.saveRecord record
'Prints-> Saving to DRIVER=Oracle Server;SERVER=myA.server.com\DatabaseA; Record with value: This is a value
End Sub
Public Sub ApplicationB()
Dim record As IRecord
Set record = New record
record.setValue ("This is a value")
Dim db As Database
Set db = DatabaseFactory.createDatabaseWithStrategyB
db.saveRecord record
'Prints-> Saving to DRIVER=SQL Server;SERVER=myB.server.com\DatabaseB; Record with value: This is a value
End Sub
Как видите, strategy-pattern
в сочетании с Factory-Pattern
помогает вам исключить большую часть повторяющегося кода для инициализации и установить стратегию для вашей базы данных class
.
Надеюсь, это поможет.