I want to learn about Design Patterns and be able to apply them in Excel VBA. So to learn about patterns I bought a book that seems promising: Head First Design Patterns; it presents the material clearly. However, the code exercises/examples are in Java 8. VBA does not have direct counterparts for some things (e.g. Extends) so I need to work out how to accomplish the same/similar in VBA.
I am following along with the exercises and doing what I think parallels the Java in VBA. What I am asking here is "am I on the right track?"
More detail: the specific aspect (I think) is the Extends use in Java (MallardDuck Extends Duck); VBA has no Extends, so the specific question would be does the technique I used of passing the Duck to my VBA MallardDuck in the Create method and setting the fly and quack behaviors accomplish the Extends use in Java?
Here’s the Java for a part of on exercise:
public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; } public void setQuackBehavior(QuackBehavior qb) { quackBehavior = qb; } abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void swim() { System.out.println("All ducks float, even decoys!"); } } public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); } public void display() { System.out.println("I'm a real Mallard duck"); } } public class MiniDuckSimulator { public static void main(String[] args) { MallardDuck mallard = new MallardDuck(); FlyBehavior cantFly = () -> System.out.println("I can't fly"); QuackBehavior squeak = () -> System.out.println("Squeak"); RubberDuck rubberDuckie = new RubberDuck(cantFly, squeak); DecoyDuck decoy = new DecoyDuck(); Duck model = new ModelDuck(); mallard.performQuack(); rubberDuckie.performQuack(); decoy.performQuack(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); } }
Here's what I’ve done in VBA - There are some differences in the Main procedures because I haven't completely mimicked the Java in VBA. I am more interested in the Duck and Mallard implementations.
Any suggestions are greatly appreciated.
Duck class module:
'@Folder("SimUDuck.Objects.HeadFirst")
Option Explicit
Private Type TObject
FlyBehavior As IFlyBehavior
QuackBehavior As IQuackBehavior
DuckModel As IDuckModel
End Type
Private this As TObject
Private Sub Class_Terminate()
With this
Set .FlyBehavior = Nothing
Set .QuackBehavior = Nothing
End With
End Sub
Public Property Get DuckModel() As IDuckModel
Set DuckModel = this.DuckModel
End Property
Public Property Set DuckModel(ByVal model As IDuckModel)
With this
Set .DuckModel = model
End With
End Property
Public Property Get FlyBehavior() As IFlyBehavior
Set FlyBehavior = this.FlyBehavior
End Property
Public Property Set FlyBehavior(ByVal behavior As IFlyBehavior)
Set this.FlyBehavior = behavior
End Property
Public Property Get QuackBehavior() As IQuackBehavior
Set QuackBehavior = this.QuackBehavior
End Property
Public Property Set QuackBehavior(ByVal behavior As IQuackBehavior)
Set this.QuackBehavior = behavior
End Property
Public Sub performFly()
this.FlyBehavior.Fly
End Sub
Public Sub performQuack()
this.QuackBehavior.Quack
End Sub
Public Sub Swim()
'todo
End Sub
Public Sub Display()
this.DuckModel.Display
End Sub
MallardDuck class module:
'@PredeclaredId
'@Folder("SimUDuck.Models.HeadFirst")
Option Explicit
Private Type TModel
Display As String
End Type
Private this As TModel
Implements IDuckModel
Private Sub IDuckModel_Display()
Debug.Print this.Display '"I'm A Mallard Duck"
End Sub
Public Function CreateDuck(ByVal duck As DuckObject) As IDuckModel
With duck
Set .FlyBehavior = New FlyWithWingsBehavior
Set .QuackBehavior = New QuackBehavior
End With
With New MallardDuckModel
.Display = "I'm A Mallard Duck"
Set CreateDuck = .Self
End With
End Function
Public Property Get Self() As IDuckModel
Set Self = Me
End Property
Public Property Get Display() As String
Display = this.Display
End Property
Public Property Let Display(ByVal value As String)
this.Display = value
End Property
Public Sub MainDuck()
Dim duck As DuckObject
Set duck = New DuckObject
With New MallardDuckModel
Dim model As IDuckModel
Set model = .CreateDuck(duck)
End With
With duck
Set .DuckModel = model
.performFly
.performQuack
.Display
Dim FlyBehavior As IFlyBehavior
Set FlyBehavior = New FlyRocketPoweredBehavior
Set .FlyBehavior = FlyBehavior
Dim QuackBehavior As IQuackBehavior
Set QuackBehavior = New SqueakBehavior
Set .QuackBehavior = QuackBehavior
.performFly
.performQuack
.Display
End With
Set duck = New DuckObject
With New ModelDuckModel
Set model = .CreateDuck(duck)
End With
With duck
Set .DuckModel = model
.performFly
.performQuack
.Display
End With
End Sub