-
Mar 1st, 2014, 04:23 PM
#1
Thread Starter
New Member
Wrapping an object with another in VB 2013
I am trying to wrap an instance of a created class with another that share the same super class in Visual Basic 2013. I'm new to VB and been struggling with this.
This is for a Java to VB conversion..
Code example of what I have written:
Code:
' Abstract product creator Class
Public MustInherit Class PizzaMaker
' Abstract Method to create a pizza
Public MustOverride Function createPizza(ByRef size As Integer, ByRef crust As String) As Pizza
Public Function orderPizza(ByRef size, ByRef crust) As Pizza
Dim pizza As Pizza
pizza = createPizza(size, crust)
Return pizza
End Function
End Class
' Concrete factory Class
Public Class MargheritaMaker
Inherits PizzaMaker
' Override abstrat method in superclass
Public Overrides Function createPizza(ByRef size As Integer, ByRef crust As String) As Pizza
Dim pizza As New MargheritaPizza(size, crust)
Return pizza
End Function
End Class
' Abstract component product Class
Public MustInherit Class Pizza
' Consatant variables used for pizza size
Public Const SMALL As Integer = 1
Public Const MEDIUM As Int16 = 2
Public Const LARGE As Int16 = 3
Public Const EXTRA_LARGE As Int16 = 4
' Crust type of pizza
Private crustType As String
' Size of the pizza
Private size As Int16
' Description of the pizza
Public description As String = "Pizza"
' Abstract method to return the cost of the pizza
Public MustOverride Function getCost() As Double
' Returns size description
Public Function getSizeDescription() As String
Dim desc As String
' Determin pizza size and return String description
If (size = 1) Then
desc = "Small"
ElseIf (size = 2) Then
desc = "Medium"
ElseIf (size = 3) Then
desc = "Large"
Else
desc = "Extra Large"
End If
Return desc
End Function
Public Function getCrust() As String
Return crustType
End Function
' Sets the pizza crust type
Public Sub setCrust(ByRef crust)
crustType = crust
End Sub
' Returns the pizza size
Public Function getSize() As Integer
Return size
End Function
' Set the size of our Pizza
Public Sub setSize(ByVal i)
size = i
End Sub
' Returns the String description of the pizza
Public Function getDescription() As String
Return getSizeDescription() + " " + crustType + " " + description
End Function
End Class
' Concrete component product Class defining a Margherita Pizza
Public Class MargheritaPizza
Inherits Pizza
'Dim cost
' Constructor set's the Pizza size, crust type & description
Sub New(ByRef size As Integer, ByRef crust As String)
setSize(size)
setCrust(crust)
description = "Margherita Pizza"
End Sub
' Returns the Pizza base cost based on it's size
Public Overrides Function getCost() As Double
Dim cost As Double
If (getSize() = Pizza.SMALL) Then
'Console.Write("in if" & vbNewLine)
cost = 9.5
ElseIf (getSize() = Pizza.MEDIUM) Then
cost = 10.5
ElseIf (getSize() = Pizza.LARGE) Then
cost = 11.5
ElseIf (getSize() = Pizza.EXTRA_LARGE) Then
cost = 12.5
End If
'Console.Write("in if" * vbNewLine)
Return cost
End Function
End Class
' Abstract component product decorator Class
Public MustInherit Class PizzaDecorator
Inherits Pizza
' Abstract method that returns decorator description
Public MustOverride Overloads Function getDescription()
End Class
' Concrete component product decorator Class (used as Object wrapper)
Public Class Cheese
Inherits PizzaDecorator
Dim pizza ' As Pizza
' Check that the construtor paramaters are correct!!! Also check scope of variables!!!
Sub New(ByVal pizz)
pizza = pizz
'pizza.setSize(pizz.getSize())
'pizza.setCrust(pizz.getCrust())
End Sub
' Returns cost of product by delegating call to wrapped objects
Public Overrides Function getCost() As Double
Dim cost ' As Double = pizza.getCost()
If (pizza.getSize() = pizza.SMALL) Then
Console.Write(" In cheese pizza = SMALL" & vbNewLine)
cost += 0.1
ElseIf (pizza.getSize() = pizza.MEDIUM) Then
cost += 0.2
ElseIf (pizza.getSize() = pizza.LARGE) Then
cost += 0.3
ElseIf (pizza.getSize() = pizza.EXTRA_LARGE) Then
cost += 0.4
End If
Console.Write(" Pizza size = " + pizza.getSize().ToString & vbNewLine)
Console.Write(" in end if" & vbNewLine)
Return cost + pizza.getCost()
End Function
Public Overrides Function getDescription() As Object
Return pizza.getDescription() + ", Extra Cheese"
End Function
End Class
Then run a test with this:
Code:
Public Class TestForm
Public margheritaM ' As MargheritaMaker
Public pizza ' As Pizza
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Dim m As New MargheritaMaker()
'Dim pizza
'Dim margheritaM As New MargheritaMaker()
margheritaM = New MargheritaMaker()
pizza = margheritaM.createPizza(1, "Deep Pan")
MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub
Private Sub CheeseButton_Click(sender As Object, e As EventArgs) Handles CheeseButton.Click
'pizza As New Cheese(pizza)
pizza = New Cheese(pizza)
MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub
Private Sub CostButton_Click(sender As Object, e As EventArgs) Handles CostButton.Click
MargheritaBox.AppendText(pizza.getCost() & vbNewLine)
End Sub
Private Sub PepperoniButton_Click(sender As Object, e As EventArgs) Handles PepperoniButton.Click
pizza = New Pepperoni(pizza)
MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub
End Class
I assumed I could create a MargheritaPizza objcet with Button1 click and assign a pizza object to pizza via it's factory method createPizza
then on cheeseButton click I could wrap the pizza object created with the call pizza = New Cheese(pizza)!! The cheese class encapsulates the extra topping for the pizza. I thought that I could then call cost on the original pizza object wiich would delegate the cost through the wrapped objects?? As in the Decorator Pattern.
Some screen shot of output below:
Here I clicked create pizza then calculate cost then extra cheese finally calculate cost, all seems well!
This time I also clicked extra cheese and calculate cost, but the cost is not delegating through the objects correctly!
Here I added several extra cheese and also show some output to the console window for the test, the console window shows the size of the pizza each time the object is wrapped and shows that pizza size is 0 except on the inner most wrapper...What am I doing wrong??
My first language is Java and have no problem with this technique in the past, but new to VB 2013 and appreciate some help here..
All constructive comments welcome.
Many thanks
Please ignore code that's been commented out during testing
-
Mar 1st, 2014, 06:33 PM
#2
Re: Wrapping an object with another in VB 2013
What is the point of the PizzaMaker and derived classes? All they do is create an instance of a certain type of pizza and return it. You could do that directly without the need for a factory. I suppose that you could create a factory that took a type of pizza, a size, and a crust, create that and return it, but in that case there would never be a need for any classes to be derived from the PizzaMaker class, and even then, PizzaMaker just seems like an unnecessary layer of complication. If you know that you need a pizza of type X, why not just create a new pizza of type X? Why use a factory at all?
The sizes you have as constants in Pizza should actually be an Enum declared outside of Pizza. After all, you want to be able to pass in a PizzaSize rather than converting between 1 and Small, 2 and Medium, and so forth. An Enum would work better for this as it would get rid of the need to do all that converting back and forth.
What is Crust, and why is it being passed ByRef? It seems like it should be another Enum, but I don't see it (there is a lot of stuff there, so perhaps I just overlooked it, or perhaps you left it out as irrelevant).
The Decorator class looks like a mistake. After all, you have it deriving from Pizza, but it appears to be modifications of toppings. That gets the IsA/HasA relationship backwards. A Pizza HAS Decorations, but a Pizza is NOT a Decoration, nor is a Decoration a Pizza.
Frankly, it all seems like death by Object Orientation, which is a common pitfall to OO design. I generally like the idea that there be a base Pizza class with a bunch of classes derived from that for individual types. I like the idea of different sizes and crust types, but both of those should be enums, as they just become members in the base Pizza class. Aside from that, the rest seems like overkill. I don't see the point in the PizzaMaker, or the base/derived Decorator class. The Decorator class seems fine, except that it shouldn't derive from Pizza, or necessarily know anything about the Pizza. The Pizza should have a List(of Decorator) as a member. The Decorator class might have a base method for CostAddition, which can be overriden in each derived class (cheese, pepperoni, etc.). The CostAddition method would take the size as an argument and return the additional cost that the Decoration adds to the base cost of the pizza. When you call the GetCost method of Pizza, it would calculate a base cost, then iterate through the list of Decorator calling the CostAddition method for each one.
My usual boring signature: Nothing
-
Mar 3rd, 2014, 05:42 AM
#3
Re: Wrapping an object with another in VB 2013
Originally Posted by TripVoltage
Here I added several extra cheese and also show some output to the console window for the test, the console window shows the size of the pizza each time the object is wrapped and shows that pizza size is 0 except on the inner most wrapper...What am I doing wrong??
Okay, what happens when you call getSize() on your decorated pizza? It's an instance of Cheese, which doesn't override the getSize method, so let's look at PizzaDecorator, that doesn't override getSize(), so let's look at Pizza: ah, it returns the value in the size field. The size field of the current instance. Has anything filled in that field on the current instance? Which object's size field should we be checking? I think maybe the underlying Pizza instance that we're decorating perhaps? And which class should be responsible for retrieving the value?
Originally Posted by TripVoltage
My first language is Java
You can rather see this from your property declarations. VB has first class support for properties, so you wouldn't expect to find setX and getX methods in your classes, instead you would tend to define them as a Property:
vbnet Code:
Private _size As Integer
Public Property Size As Integer
Get
Return _size
End Get
Set(value As Integer)
_size = value
End Set
End Property
Or inthis case, since you're just setting and retrieving a backing field, you can use the auto-property shorthand:
vbnet Code:
Public Property Size As Integer
Originally Posted by Shaggy Hiker
The Decorator class looks like a mistake. After all, you have it deriving from Pizza, but it appears to be modifications of toppings. That gets the IsA/HasA relationship backwards. A Pizza HAS Decorations, but a Pizza is NOT a Decoration, nor is a Decoration a Pizza.
This is the Decorator Pattern. Decorator is not referring to something in the problem domain, it is not a decoration on a pizza, it is a decoration of the Pizza class that adds or modifies behaviour of that class. As such, yes, it should wrap an underlying instance of Pizza. What you should read it as is "a Pizza that is the same as the underlying Pizza, but with added cheese".
Originally Posted by Shaggy Hiker
Frankly, it all seems like death by Object Orientation, which is a common pitfall to OO design.
It's not "Death by OO", more "constrained example that could not possibly hope to be complex enough to justify the architecture that is being demonstrated, so just pretend it's justified and watch the mechanics of how it works". Admittedly, that doesn't roll off the tongue quite as nicely.
-
Mar 3rd, 2014, 10:40 AM
#4
Re: Wrapping an object with another in VB 2013
That IS death by OO. A "constrained example that could not possibly hope to be complex enough to justify the architecture that is being demonstrated" is where the problem comes from. People have some OO design and therefore decide that every problem has to be stuffed into the design. It's a fine example of putting form over function, which is what leads to horribly complicated, overblown, OO heirarchy trees. Now, perhaps this is some kind of class exercise, but if so, what is the objective of the teaching? How to stuff square pegs into round holes, perhaps? How to confuse the students by asking them to inappropriately apply some principle?
My usual boring signature: Nothing
-
Mar 3rd, 2014, 11:19 AM
#5
Re: Wrapping an object with another in VB 2013
No, it's not Death by OO. It would be Death by OO if this sort of architecture was suggested for a problem if this complexity, but it's not being recommended for a problem of this complexity. It is simply demonstrating the moving parts of the approach on a highly simplified example so that the example does not get in the way of the code being demonstrated.
If we were looking at a system with sufficient complexity to warrant such an approach, you'd be looking at several pages worth of forum posts just explaining the problem domain, and then a multi MLOC code post. Are you expecting to be able to learn the pattern being demonstrated from that?
Either 1) Ignore the fact that the complexity of this example does not warrant the architecture being discussed and pretend that it is justified or 2) come up with a sufficiently complex example to justify it that can be concisely conveyed.
Hard though it may be to believe, this approach does have some validity when you are dealing with complex domains.
-
Mar 3rd, 2014, 12:13 PM
#6
Re: Wrapping an object with another in VB 2013
Actually, you are making quite an assumption when you assume that this is just a class exercise to demonstrate a technique. The OP stated up front that this is for a Java to VB conversion. It is possible that the OP found a solution to a class exercise written in Java, or it is possible that the the class is something about a comparison between Java and VB, but the latter seems improbable and the former not so likely.
My usual boring signature: Nothing
-
Mar 3rd, 2014, 12:14 PM
#7
Re: Wrapping an object with another in VB 2013
I'm pretty sure it's attempting to translate the example from Head First Design Patterns book into VB, actually. There's definitely an example of the Factory Pattern involving making Pizzas, pretty sure it goes off the rails like this trying to demonstrate the Abstract Factory Pattern.
-
Mar 3rd, 2014, 12:18 PM
#8
Re: Wrapping an object with another in VB 2013
Wow. You recognize a question from a book? Frankly, that IS impressive. I haven't been reading enough books like that, but even if I did, I doubt I would have retained enough about some example to recognize it in a forum post.
My usual boring signature: Nothing
-
Mar 14th, 2014, 07:22 AM
#9
Thread Starter
New Member
Re: Wrapping an object with another in VB 2013
Originally Posted by Evil_Giraffe
I'm pretty sure it's attempting to translate the example from Head First Design Patterns book into VB, actually. There's definitely an example of the Factory Pattern involving making Pizzas, pretty sure it goes off the rails like this trying to demonstrate the Abstract Factory Pattern.
Hi Giraffe, your correct. I am trying to use the patterns for my Pizza Shop assignment from Design Patters Head First and well spotted. I did question the complexity myself after reading the chapters then thought maybe things would become clearer with experience! Now actually having finished the book the OO complexity talked about here was simplified and a much simpler solution was reached. Maybe I should have completed the whole book before attempting my solution but hey at least I'm trying to understand what design patterns are and attempting to use them is my solutions. Like I said with experience I will have a much better understanding of what to use and when over time.
Thanks
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|