Results 1 to 9 of 9

Thread: Wrapping an object with another in VB 2013

  1. #1

    Thread Starter
    New Member
    Join Date
    Feb 2014
    Posts
    3

    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:

    Name:  Capture1.jpg
Views: 554
Size:  6.0 KB

    Here I clicked create pizza then calculate cost then extra cheese finally calculate cost, all seems well!

    Name:  Capture2.jpg
Views: 568
Size:  7.2 KB

    This time I also clicked extra cheese and calculate cost, but the cost is not delegating through the objects correctly!

    Name:  Capture3.jpg
Views: 485
Size:  7.1 KB
    Name:  Capture4.PNG
Views: 553
Size:  3.2 KB

    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

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    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

  3. #3
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Wrapping an object with another in VB 2013

    Quote Originally Posted by TripVoltage View Post
    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?

    Quote Originally Posted by TripVoltage View Post
    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:
    1. Private _size As Integer
    2. Public Property Size As Integer
    3.     Get
    4.         Return _size
    5.     End Get
    6.     Set(value As Integer)
    7.         _size = value
    8.     End Set
    9. End Property

    Or inthis case, since you're just setting and retrieving a backing field, you can use the auto-property shorthand:

    vbnet Code:
    1. Public Property Size As Integer


    Quote Originally Posted by Shaggy Hiker View Post
    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".

    Quote Originally Posted by Shaggy Hiker View Post
    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.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    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

  5. #5
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    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.

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    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

  7. #7
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    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.

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    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

  9. #9

    Thread Starter
    New Member
    Join Date
    Feb 2014
    Posts
    3

    Re: Wrapping an object with another in VB 2013

    Quote Originally Posted by Evil_Giraffe View Post
    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
  •  



Click Here to Expand Forum to Full Width