Understanding Bridge Pattern using .NET
page 8 of 13
by David Simmonds
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 47011/ 94


This will instantiate a default Abstractor (in this case a VerbalEvaluation).  It also configures the default renderer with a default Implementer (in this case a Fish renderer).  So the form is ready to go as soon as it loads.

When the user clicks on an evaluation control (such as the track bar, numericupdown or list box) the class which wraps that control becomes instantiated by the client.  That abstractor will now be responsible for interpreting user inputs and converting them into abstractions (the score).  In order to fulfill the intent of the pattern, the form maintains a reference to the Abstraction class AND the Implementer class.  This means that whenever we destroy one or the other, we can easily reconfigure the new class with the existing one.  The user never has to do two selections before seeing a rendition of the rating.

We also perform a little trick when we are changing an implementer class.  In order to clear the picture box which is becoming inactive, we allow the form to send an instruction to the implementer to render a “0” score (which clears the graphic surface).  This allows us to display just one graphical rendition of the score at a time.  This is done purely for aesthetic reasons.

Now ideally, we would also have a routine which disables controls which are not active, so we would see only one evaluation at a time.  However, time does not permit this.  The reader could attempt this implementation if they so desire.

Listing 3

Private Sub frmRatingShell_Load(...)Handles MyBase.Load
    Me.RenderingImplementor = New     
    Implementors.FishRenderer(Me.pbxFishes, Me.imlFish)
    Me.AbstractEvaluator = New Abstractors.VerbalEvaluation
                 ( Me.VerbalEval, Me.RenderingImplementor)
    End Sub 
Private Sub SlidingBar_Scroll(…) _
                          Handles SlidingBar.Scroll
End Sub
Private Sub NumericEval_ValueChanged(…) _
                       Handles NumericEval.ValueChanged
End Sub
Private Sub pbxFaces_Click( …) Handles pbxFaces.Click
End Sub
Private Sub pbxFishes_Click( … ) Handles pbxFishes.Click
End Sub
Public Function ChangeEvaluator(ByVal EvaluatorType As String)
  ' This is a makeshift “factory-function” which instantiates     
  '      the Abstractors for us
  '     We could just as easily have used Prototype Pattern
  Me.AbstractEvaluator = Nothing
  Select Case EvaluatorType
         Case "Verbal"
            AbstractEvaluator = New Abstractors.VerbalEvaluation                                
                              (VerbalEval, RenderingImplementor)
         Case "Sliding"
      AbstractEvaluator = New Abstractors.SlidingEvaluation _   
                         (SlidingBar, RenderingImplementor)
      Case "Numeric"
          AbstractEvaluator = New Abstractors.NumericEvaluation
                             (NumericEval, RenderingImplementor)
      End Select
End Function
Public Function ChangeRenderer(ByVal RendererType As String)
  ' Clears the graphic surface of the Implementor we are 
  '    decomissioning
  Me.RenderingImplementor = Nothing
  ' This statement-block figures out which implementor to
  '    instantiate. 
  '    It assigns the new implementor to the Parent container 
  '    which is the form
  '    so that even when we destroy the Abstractor, 
  '    the implementor is kept alive
  '    and we can commission it back into use by assigning it to 
  '    the new Abstractor
  Select Case RendererType
      Case "Faces"
         Me.RenderingImplementor = New Implementors.FaceRenderer
                                  (Me.pbxFaces, Me.imlFace)
      Case "Stars"
         Me.RenderingImplementor = New Implementors.StarRenderer 
                                  (Me.pbxStars, Me.ImlStar)
        End Select
 ' Takes the reference to the implementor which the Form keeps
 '   and assigns it to the new Abstractor
  Me.AbstractEvaluator.RatingRenderDevice = _ 
End Function
End Class

Opportunities for and Costs of - Adaptation and Extension

Adaptation is easy in the bridge pattern.  Modification of a refined abstraction or a concrete implementation requires absolutely no testing of the other classes in the system.  That is unless you do something like (in this case) changing the rating scale which the class uses.  This would force you to revise all the classes throughout the system.  That is more than just a change to a class, right?  If you look at the pattern tweaking section, you will see a discussion on the expansion of the bridge pattern which includes the incorporation of a signal class and the way in which it ensures that programmers do not mistakenly change the outputs of refined abstractions or the inputs to concrete implementers in an arbitrary manner in the course of maintaining the abstraction/implementation classes.

So unexpected blunders aside, we can maintain abstractions and implementations in a very discrete way.  The same way we could change almost any wiper-blade in a wiper without affecting the wiper motor (another example of the bridge system in real life).

In the same vein, we can add more abstractions or implementations without affecting the others in the system.  There is nothing we have to do to register new abstractions/implementations either; we simply make use of them in the client.  The client simply instantiates the new implementation and configures a new abstraction with it, calling the relevant operation on the abstraction to do the work required.

View Entire Article

User Comments

No comments posted yet.

Product Spotlight
Product Spotlight 

Community Advice: ASP | SQL | XML | Regular Expressions | Windows

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-13 12:57:45 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search