Download Professional Design Patterns in VB NET Building Adaptable Applications 1st Edition Tom Fischer ebook All Chapters PDF
Download Professional Design Patterns in VB NET Building Adaptable Applications 1st Edition Tom Fischer ebook All Chapters PDF
com
https://ebookgate.com/product/professional-design-patterns-
in-vb-net-building-adaptable-applications-1st-edition-tom-
fischer/
OR CLICK HERE
DOWLOAD NOW
https://ebookgate.com/product/professional-optical-system-design-
fischer/
ebookgate.com
https://ebookgate.com/product/professional-asp-net-3-5-sp1-edition-in-
c-and-vb-bill-evjen/
ebookgate.com
https://ebookgate.com/product/mastering-asp-net-with-vb-net-1st-
edition-a-russell-jones/
ebookgate.com
https://ebookgate.com/product/beginning-asp-net-3-5-in-vb-2008-from-
novice-to-professional-2nd-edition-matthew-macdonald-macdonald-m/
ebookgate.com
Beginning ASP NET 1 1 with VB NET 2003 1st Edition Chris
Ullman
https://ebookgate.com/product/beginning-asp-net-1-1-with-vb-
net-2003-1st-edition-chris-ullman/
ebookgate.com
https://ebookgate.com/product/high-performance-responsive-design-
building-faster-sites-across-devices-1st-edition-tom-barker/
ebookgate.com
https://ebookgate.com/product/building-web-applications-with-ado-net-
and-xml-web-services-1st-edition-richard-hundhausen/
ebookgate.com
Tom Fischer
John Slater
Pete Stromquist
ChaurG. Wu
A l l rights reserved. No part of this work may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording, or by any information
storage or retrieval system, without the prior written permission of the copyright owner and the
publisher.
Trademarked names may appear in this book. Rather than use a trademark symbol with every
occurrence of a trademarked name, we use the names only in an editorial fashion and to the
benefit of the trademark owner, with no intention of infringement of the trademark.
Distributed to the book trade in the United States by Springer-Verlag New York, Inc., 175 Fifth
Avenue, New York, NY, 10010 and outside the United States by Springer-Verlag GmbH & Co.
KG, Tiergartenstr. 17, 69112 Heidelberg, Germany.
For information on translations, please contact Apress directly at 2560 Ninth Street, Suite 219,
Berkeley, CA 94710. Phone 510-549-5930, fax 510-549-5939, email [email protected], or visit
http://www.apress.com.
The information in this book is distributed on an "as is" basis, without warranty. Although every
precaution has been taken in the preparation of this work, neither the author(s) nor Apress shall
have any liability to any person or entity with respect to any loss or damage caused or alleged to
be caused directly or indirectly by the information contained in this work.
The source code for this book is available to readers at http://www.apress.com in the Downloads
section.
Credits
Tom Fischer
Tom Fischer's career spans a broad range of technologies, working with some of the most
prestigious consulting firms in the Twin Cities. His certifications include the Sun Certified Java
Programmer (SejP), Microsoft Certified Solution Developer (MCSD), and Microsoft Certified
Database Administrator (MCDBA).
As a Microsoft Certified Teacher (MCT), Tom also helps teach other developers about the latest
.NET tools and technologies.
I would like to dedicate my contributions to Theresa, Ali, and Kate. They are the greatest! - TF
John Slater
John Slater is a project manager at Management Reports International in Cleveland, OH. At
MRI he is currently developing applications for the property management industry. Right now,
he is working on several projects using .NET development tools and .NET Enterprise servers.
In his free time John enjoys outdoor activities and playing with his children Rachel and Nathan.
He can be reached [email protected].
Pete StromquIst
Pete Stromquist is a consultant at Microsoft Technologies (one of the nation's premier Microsoft
Certified Solution ProViders), specializing in web-enabled application development using
Microsoft tools and technologies. He has spent the last several years architecting and developing
the following types of applications: intranet content management, web-enabled training and
testing software, B2B and B2C e-commerce, and web-based telemetry and logistics. He has
complemented his VB skills with several other technologies such as: XML, XSL, COM+, lIS,
ASP, and of course .NET.
Pete also enjoys teaching and presenting on .NET technologies. He has a Mechanical
Engineering background, and received his Bachelor of Science from the University of Minnesota.
ChaurG. Wu
Chaur Wu currently works for Trend Micro Inc. as a senior software engineer. He started
software programming before he was old enough to qualify for a driving license. The first
program he wrote was a bingo game - in assembly code on an 8051 Single chip. To capitalize on
the program, he ran a small casino in the lab - he developed primitive game boxes that
connected his pals and allowed them to place bets.
He's also been involved in much larger projects. For example, he developed a program in C++
to simulate the movement and geographical coverage of GPS satellites. As a research assistant in
his graduate study, he implemented a wavelet-based video compression algorithm for a traffic
surveillance system sponsored by Boston City Department of Transportation. He also helped
solve a blurred image problem using inverse filters and other image processing algorithms for a
client who designs fiber optics components in San Jose, CA.
His technical interests include distributed software systems inJava, COM, and .NET, generative
programming, software deSign, and neural networks. Outside of work, his favorite vacation combines
a one-night gambling trip to Reno followed by a day of skiing at some resort near Lake Tahoe.
-..... .'.
-~.
.0-
Table of Contents
Introduction 1
Who Is This Book For? 2
What Does This Book Cover? 2
What This Book Does Not Cover 3
Summary 66
ii
Table of Contents
Summary 175
iii
Table of Contents
Summary 252
Chapter 5: Between the Tiers: Design Patterns and .NET Remotlng 255
.NET Remotlng - A Primer 256
Remoting Objects and the Host Server 256
Channels and Protocols 257
iv
Table of Contents
Antlpatterns 300
The Antipatterns Bible 301
The Blob 301
Lava Row 301
Poltergeists (aka Proliferation of Classes) 302
v
Table of Contents
Summary 334
vi
Table of Contents
vii
r ---!:.::-=
~
- -- -~-JI-f~--~
-~~·------·-·----
;
:r-l_.'~- ··-·--"~'-~~--~=
;
: .•
~
·• ==1Tfu_,_·_~.._..-~-_-~~~l,.
_--
:
---'-- · ... _
f::/lii~:~::'-;-~··:-T -~~
.."- '. < •... - - _ . :
-:~~·:~L:~:L_
_ _I
".
:
:
··i
.
, :
.. -.-. .-.
Introduction
It is perhaps easiest to think of a design pattern as a template for a solution. When presented with a
problem, the first thing we do is identify the defining characteristics of the problem. Then, we examine
our armoury to see whether we have a generic solution that solves the problem we've characterized. If
so, we apply the solution template and hence solve the problem.
The design pattern itself describes both the defining characteristics of the problem and the
characteristics of the solution. The solution template is tried and tested, which means that once we've
correctly identified which pattern to use, we can apply it without the need to do research and proof-of-
concept testing.
This process is one that applies in all walks of life - architecture, medicine, furniture restoration ... Not
all disciplines use the term "design pattern", but in any case the process is the same. This book is about
design patterns in object-oriented programming (OOP).
So, a design pattern in OOP is a solution template - it describes the characteristics of the problem and of
the solution, but leaves you {the developer} to implement the details of the solution. Design patterns are
not about programming "tricks"; rather, they penetrate to the heart of the problem at hand, and allow
you to break things down into constituent parts. Design patterns help you see the path toward the
overall solution, without dictating it.
This book draws on the work of the Gang of Four {or GoF} - Erich Gamma, Richard Helm,
RalphJohnson, and John Vlissides - whose seminal book Design Patterns: Elements o/Reusable Object-
Oriented Software {Addison-Wesley, ISBN 0-201-63361-2} describes the fundamentals of design patterns
in OOP and catalogs 23 design patterns in significant detail.
Introduction
Design patterns rely on true 00 capability in the production language. Unlike previous incarnations of
Visual Basic, VB.NET is truly object-oriented and requires a rather different mindset. In this book we
will put the focus on using design patterns with VB.NET, and on how to put the GoF patterns (and other
patterns) to use in that context.
The book does not assume that you have any knowledge of design patterns, but it does assume
familiarity with Visual Basic .NET. Some knowledge of OOP and/or UML will also help the reader to
appreciate this book, because most of the design patterns are built on 00 principles and described
using UML diagrams.
This book does contain a UML Primer (in Appendix A), and thus is not intended to exclude readers who
are not well-versed in OOP and UML. For those readers, this book uses UML to describe some
fascinating and generic applications of 00 principles, and should make a good companion to a "first
principles" book on OOP or UML. We do not explain the basics of OOP or UML during the course of
the chapters themselves - instead, we expect that the reader is already armed with some experience or
is willing to fill in the gaps.
Cl Readers who are familiar with VB.NET and wish to use 00 techniques like design patterns to
get more from the language and from their application architecture
Cl Readers who have seen the GoF Design Patterns book, and wish to see some of the GoF
patterns and other patterns demonstrated in VB.NET
Cl Readers who have tried implementing design patterns in Visual Basic, and wish to learn how
the true 00 nature of VB.NET makes the whole thing much easier
This is a fundamentally practical book, and for the VB.NET developer it makes a good companion to
the more theoretical GoF Design Patterns book.
In Chapters 2-4, we examine three case studies, each of which examines the role of design patterns in
one of the three tiers of a classical 3-tier application. Chapter 2 takes the data tier, Chapter 3 takes the
middle (business logic) tier, and Chapter 4 takes the presentation tier. These case studies provide us
with a number of lessons. For example:
2
Introduction
OWe discuss the process of recognizing the characteristics of a design pattern within a given
problem, and hence design a solution architecture that is based on that pattern
OWe examine implementations of GoF patterns and other patterns (in isolation and in
combination)
OWe look at how to translate patterns into code
o We highlight the advantages gained by applying patterns to particular problems
Although they are similar, each of these case studies is a stand-alone study designed to focus on the
relevance and implementation of design patterns in the context of one particular tier.
To complement the main three case studies, Chapter 5 examines .NET Remoting - a candidate
technology for tying together the distributed tiers of a .NET application. Chapter 5 is not an
introduction to .NET Remoting, but looks at the subject of .NET Remoting from a design patterns point
of view. In it, we look at how design patterns have been built into the principles of .NET Remoting from
the start, and how .NET Remoting also supports the developer who uses design patterns in his remoting
implementations.
Chapter 6 rounds off the book by suggesting some related areas and subjects that follow on naturally
from a study of design patterns. It also includes a selection of resources, references, and further reading.
The book also does not teach VB.NET, OOP, or UML; it is assumed that the reader has some
familiarity with these subjects or is willing to fill in the gaps where necessary. However, as we've already
mentioned, there is a UML Primer contained in the back of the book, in AppendiX A - this is intended as
a qUick tutorial or reference in UML.
o A suitable operating system. Either Windows 2000 Professional, Server or Advanced Server
Edition (at the time of writing, the latest service pack is SP2), or Windows XP
Professional Edition.
o The .NET Framework SDK.
o In Chapters 1-4, we use the Visual Studio .NET IDE to build and compile applications. In fact,
VB.NET ships with both the .NET Framework SDK and Visual Studio .NET; it is possible to
buiild and compile these applications without VS.NET, using the command-line tools that ship
with the .NET Framework SDK. We use the command-line compiler only in Chapter 5.
3
Introduction
o Chapters 2 and 3 make use of a SQL Server 2000 database server. If you don't have access to
a SQL Server installation, you can run the examples using the SQL Server Desktop Engine
(also known as MSDE).
MSDE is shipped with the .NET Framework SDK, and also with VS.NET. To install it, execute
the file InstMSDE.exe (which is found in the IProgram FileslMicrosoft.NET
IFrameworkSDKlSampleslSetuplMSDE folder). MSDE does not offer the same admin tools as
Sf& Server, but there are some useful command-line utilities detailed in the file
IProgram FileslMicrosoft.NEnFrameworkSDKISampleslSetuplhtml
IConfigDetails.htm. Moreover, note that VS.NET provides an arguably better UJ to a SQ,L
Server database.
o Chapter 3 makes use of a "legacy" class library application. We provide both the source code
and the compiled DLL for this application. You don't need to build it yourself. However, if
you want to compile the DLL for yourself, you'll need Visual Basic 6.0 to do it.
o Chapter 5 makes use of MSMQ, and Chapters 2 and 4 make use of lIS 5.0. These Windows
Components ship with all versions of Windows 2000 and also with Windows XP Professional
Edition. Some editions do not install MSMQ and lIS as part of the default OS installation -
you can install them manually from the Control Panel I Add/Remove Programs dialog.
Style Conventions
We have used certain layout and font styles in this book that are designed to help you to differentiate
between the different kinds of information. Here are examples of the styles that are used, with an
explanation of what they mean.
As you'd expect, we present code in two different ways: in-line code and displayed code. When we need
to mention keywords and other coding specifics within the text (for example, in discussion relating to an
if . . . else construct or a class or object) we use the single-width font as shown in this sentence. If we
want to show a more substantial block of code, then we display it like this:
Sometimes, you will see code in a mixture of gray and white backgrounds, like this:
4
Introduction
In cases like this, we use the gray shading to draw attention to a particular section of the code - perhaps
because it is new code, or it is particularly important to this part of the discussion. We also use this style
to show output that is displayed in the console window.
Advice, hints, and background information comes in an indented, italicized font like this.
[mportant pieces of information (that you really shouldn't ignore) come in boxes like this!
Bulleted lists appear indented, with each new bullet marked as follows:
Whether you want to type the code in or not, it's useful to have a copy of the source code handy. If you
like to type in the code, you can use our source code to check the results you should be getting - they
should be your first stop if you think you might have typed in an error. By contrast, if you don't like
typing, then you'll definitely need to download the source code from our web site! Either way, the
source code will help you with updates and debugging.
Therefore all the source code used in this book is available for download at http://www.apress.com.
Once you've logged on to the web site, simply locate the title (either through our Search facility or by
using one of the title lists) . Then click on the Source Code link on the book's detail page and you can
obtain all the source code.
The files that are available for download from our site have been archived using WinZip. When you
have saved the attachments to a folder on your hard drive, you need to extract the files using a de-
compression program such as Win Zip or PKUnzip. When you extract the files, the code is usually
extracted into chapter folders.
5
Introduction
Errata
We have made every effort to make sure that there are no errors in the text or in the code. However, no
one is perfect and mistakes do occur. If you find an error in this book, like a spelling mistake or a faulty
piece of code, we would be very grateful to hear about it. By sending in errata, you may save another
reader hours of frustration, and of course, you will be helping us provide even higher quality
information.
To find known errata and submit new errata, simply go to the appropriate book page on the Apress
website at http://www.apress.com.
forums.apress.com
For author and peer discussion, join the Apress discussion groups. If you post a query to our forums, you
can be confident that many Apress authors, editors, and industry experts are examining it. At
forums.apress.com you will find a number of different lists that will help you, not only while you read
this book, but also as you develop your own applications.
To sign up for the Apress forums, go to forums.apress.com and select the New User link.
6
Introduction
7
... -
~.~
-_-
.. . -.
.... -
Introduction to Design Patterns
In the time since developers first began to apply object-oriented techniques, something quite fascinating
has occurred. As the development community gained a better and better understanding of the
implications of OOD, it became increasingly obvious that certain types of problem were appearing over
and over again - and that similar types of problem could be solved using similar types of solution.
Around the world, experienced software engineers were independently finding that they could
recognize certain specific structural (and object-related) requirements in their project design. Moreover,
each time they recognized a certain requirement, they could apply a certain object pattern to achieve
the required solution.
Over time, and by its very nature, 00 programming has spawned a common set of recognizable
problems and solutions. Thus, when a developer begins to design an application and discovers certain
problems or structures are required, they often find that that type of problem or structure has already
been identified elsewhere, and that a suitable, well-tested solution already exists.
This phenomenon has earned its own nickname - design patterns. In this chapter we will present an
introduction to design patterns by tackling the subject from three different angles:
o First, we'll take a look at what design patterns are, and what they mean to Visual Basic developers.
o Second, with the help of a fictional payroll application, we'll compare two designs and see
how the use of a design pattern can improve a VB. NET application.
o Finally, we'll explore some basic design patterns - focusing in particular on some very
common patterns and some that are relevant to this book.
Chapter 1
Design patterns are used in many walks of life. In Town Planning and Architecture, design patterns are
used to describe the characteristics of generic problems in civic and building design, and standard solution
patterns that can be applied to the problem in order to solve it. The challenge of civic designers and
architects is to recognize the patterns in real life problems, match them up to the theoretical problems of
one of the standard design patterns, and then solve the problem by applying the prescribed solution.
Note that the solution doesn't describe details of a particular implementation. Instead, it is like a
template: it describes all the necessary elements and characteristics of the solution in generic
language, and forms the basis for many implementations.
In this book, we're thinking about the concept of design patterns as applied to object-oriented programming
(OOP). In the OOP context, the principles of design patterns are similar. Each pattern consists of:
For the programmer involved in an 00 analysis and design task, the challenge is to recognize each
generic problem pattern in their project, match it to an established design pattern, and apply the
solution template to their project within their project design.
Catalogs of Patterns
This leads us to the question of where design patterns come from. Is there a definitive list of design
patterns that no 00 programmer should be without?
It's probably impossible to produce an exhaustive list of all possible design patterns, but as time goes
on, it gets harder and harder to find new, fundamental ones. While this is an interesting academic
challenge in its own right, the real purpose of design patterns is to help us build applications, and over
recent years, many of the most common patterns have been identified and documented.
There is one particularly important and famous work in this area, which we'll meet in this section.
10
Introduction to Design Patterns
The GoF's Design Patterns book catalogs 23 design patterns. They're not just a bunch of ideas that piqued
the authors' interest. These patterns represent a collection of design motifs that occur regularly in many
well-built object-oriented applications. For example, their Adapter pattern constitutes a blueprint for
converting the interface of an existing class into a different one with minimal effort. Any software
engineer who knows about the Adapter pattern knows that there is at least one tried-and-tested way to
accomplish this task without proto typing or proof-of-concept testing.
o A statement of the problem, in generic language, in the form of the pattern's intent, its
motivation, and its applicability.
o A description of the solution, in terms of its structure, a list of its participants and the
collaborations between them, the consequences of applying the pattern, implementation notes,
some sample code, some known uses and a list of related patterns.
In fact, this is indicative of an important consideration when applying design patterns in an object-
oriented environment: namely, that the production language must be truly object-oriented. The reason
for this is that 00 design patterns are built on the foundations of 00 theory - abstraction,
encapsulation, polymorphism, and (implementation) inheritance. If your intended target language is one
that lacks the key features associated with true object-oriented development, then this jeopardizes your
chances of being able to apply a pattern in that language.
This presented a problem to anyone who wanted to apply design patterns to Visual Basic application. No
version of Visual Basic (up to and including version 6.0) is truly object-oriented - in particular, VB does
not directly support implementation inheritance. The task of employing patterns in VB is tedious at best,
and any VB6 application that relies on a complex inheritance scheme requires quite a few workarounds.
11
Chapter 1
The arrival of the .NET Framework and VB.NET has dramatically changed the analysis. VB.NET is
truly object-oriented, and therefore is a good choice of production language for 00 applications whose
designs are based on design patterns.
Overnight, Visual Basic developers have acquired one of the most powerful object-oriented languages
there is. However, they've also discovered that migration from VB6 to VB.NET is more difficult than
their migrations to earlier versions of VB. While they're armed with a mastery of strange API calls and
undocumented tricks, this doesn't provide much insight into crafting sound object-oriented applications.
VB.NET programming requires a shift in mindset, to accompany the more object-oriented nature of
the language.
Fortunately, the wealth of activity that was directed at other 00 languages now provides some answers
for the VB.NET programming community. From the work done to support the application of design
patterns in languages like C++ and Smalltalk, there is a huge body of lessons learned and best practices
in the form of design patterns in all 00 languages.
It's probably helpful to list some situations in which a developer might not want to use design patterns.
After all, you wouldn't want to use a tool that adds a level of complexity unless it gives you some
discernable benefit. If any of the following applies to your current situation, then you might find that it's
not suitable to try to apply design patterns within that project:
o When the application being built today will not change, the code accurately captures all
requirements, and there are no planned enhancements or features. The application you're
building will be the first and last release. (Yeah, right.)
o Your application's code requirements are unique. No software engineer has ever built
anything like it. The program does not deal with any of those routine issues like object
creation and event notification. (Just what does it do, then?)
o There is plenty of time to prototype all of your new design ideas. Alternatively, you are so
confident of your ideas that they do not require any proof-of-concept testing.
o Everyone on your team has worked together for twenty or so years. If you ask Bill to try the
"thing-a-ma-jig" trick, he knows exactly what to do. The team already possesses a common
design vocabulary, so you don't need to learn someone else's.
12
Introduction to Design Patterns
If your situation is described in any of the above, please pass this book on to a friend. Otherwise,
keep reading.
There are two questions to keep in your head when you're trying to work out the value of design
patterns in your project. First, can you justify the presence of the pattern, even when you consider the
extra complexity and potential performance hit that it brings? Second, will the added value of a proven
design and lower maintenance bills cover the upfront investment?
WantaBeBig have specified that the target language for the application is VB.NET. They have not stated
any application design expectations.
CJ Outlined that the purpose of the TakeHomePay application is to estimate the amount of
money that a WantaBeBig employee can expect to see in their next paycheck, immediately
after submitting timesheets
CJ Stated that calculating this amount would involve several complex calculations, based on
varying country taxes, local taxes, and retirement plan contributions
CJ Included details of all of the business rules for these cumbersome calculations
CJ Noted that WantaBeBig currently operates in London and New York City and may open up
other offices over the next few years
CJ Predicted that the Personnel Manager had plans for the introduction of a second retirement plan
Unsurprisingly, the lead architects of the two consulting companies take different approaches. One
architect designs TakeHomePay in the style of a number of previous applications that his team had built
using Visual Basic 6.0. The other architect, with similar experience, elects to employ some recently
acqUired pattern knowledge in his design. We'll look at each of these designs in turn.
13
Chapter 1
1TakeHomePay I
IGetTakeHome() I
'I
I I
IUKlondonTaxNoRetlrement ! IU5NYCTaxNoRetirement I
LGetTakeHomeO I IGetTakeHomeO I
I
IUKlondonTaxRetlrement! IUSNYCTaxRetlrement I
LGetTakeHomeO I I GetTakeHomeO I
This figure is a standard UML class diagram. Ifyou're not sure how to translate it, or ifyou would
appreciate a qUick UML refresher, please refer to the UML Primer in the Appendix A.
The design is simple and straightforward, and contains just five classes in total:
CommonTakeHomePay
GetTakeHomeO
14
Introduction to Design Patterns
If you're curious about how the Decorator pattern works, but you don't want to jump ahead, you'll be
pleased to know that the mechanics of this pattern are surprisingly simple. All of the derived classes
from Decorator operate on a concrete object (CommonTakeHomePay in this example) that gets passed
around like a hot potato. For example, an instance of a CommonTakeHomePay object might first be
passed as a parameter into LondonTax. That entire object could then be passed as a parameter into
UKTax, and so on. Throughout the entire process, the derived class objects (UKTax, LondonTax, etc.) all
operate on the single original CommonTakeHomePay object.
Both lead architects decide simply to extend their existing designs to take in the new structure. At
Company N, the lead architect finds that he can model the new requirements like this:
ITakeHomePay I
I GetTakeHomeO I
Lf'
I
IUKLondonTaxRetlrementB L
LGetTakeHomeO I
IUSNYCTaxRetlrementB I
I GetTakeHomeO I
I IUSMlamlTaxRetlrementB I
IGetTakeHomeO I
As you can see, they have to add no fewer than five new classes to the existing design. There is still one
main driver class, TakeHomePay; but now there are nine supporting classes (representing the three offices
and the fact that there are now three retirement plan options - A, B and none). It's becoming clear that
further additions to the business empire will cause rapid growth in the size of this object model.
At Company P, lead architect finds that his revised model is almost identical to the original:
15
Chapter 1
CommonTakeHomePay
GetTakeHomeO
RetlrementPlanA
GetTakeHomeQ
NYCTax MiamlTax
GetTakeHomeO GetTakeHome()
One of the objects represents the new Miami office, and the other represents the new retirement plan.
This is clearly a more extensible design.
Which TakeHornePay application would you want to build or maintain? The choice is between one with
a sophisticated pattern-based architecture and one with an astronomical number of classes. Of course,
most experienced Visual Basic developers could think of several improvements for the non-pattern
design. But why bother? The Decorator pattern already solved the problem.
Remember, too, that this wasn't an exercise in finding the best way to tackle this particular problem, but
a demonstration of how a pattern could make a profound difference in the ability of your solution to
adapt to changing requirements. We'll return to this example later in this chapter, and give an
implementation of the TakeHornePay application using Company P's Decorator-based design.
Now that we've seen an example of patterns in action, let's take a tour of the different patterns
documented by the GoF.
In this section we're going to take, as a starting point, these three categories of patterns. We'll explain
the common characteristics of each category, and we'll examine in more detail some of the most
commonly used patterns in each category.
16
Introduction to Design Patterns
As I mentioned earlier, the GoF describe each pattern by using a standard template. (That is, they state
the problem in terms of the intent, motivation, and applicability, and the solution in terms of structure,
participants, etc.) This template is based on standards for documenting and describing designs that have
been developed over years; while it borders on being academic in nature, its features are useful without
exception. In particular, the intent constitutes a brief and insightful synopsis of the pattern. Here, for
each pattern we discuss in depth, we'll include a statement of the GoF's intent for that pattern quoted
from their Design Patterns book.
Note that we won't examine a1l23 of the GoF patterns in depth. The aim of this book is not to cover
ground that has already been laid by Design Patterns, but to help put things into a VB.NET perspective
with real examples. Once you've seen these more common patterns in action, you will be well equipped
to investigate and appreciate the others.
To execute the demonstration for a pattern, open the Wrox. ProDPA6985. ChOl solution in Visual
Studio .NET. View the properties for the project (by typing Shift+F4) and set the corresponding module
as the Startup object. For example, if you set the Startup object to Singleton, as shown below, and then
execute the application, it will run the Main routine that demonstrates the Singleton pattern:
r~ .PYoOPA6985.0.:1I
~1'ypO, ~ ob)ed:
1"-,,
Referl!lnCe Path ;:'lconsoIe
~':':AppIc-:-otlon-'---3"'
. rr::SIn;jeton""7':'--'--:-::':'~-~-~-~-~-~
--:-::13
~DeI_
Roct_o: ~
C""'~otlon Propettlos IWro•. ProDl'A6985.ChOI
WOtIMtIoo
Proloct fold." C:\ProJo<ts\Wrox.PYoOPA6985.ChOI\
ProJo<t"-, Wr... Prolll'A6965.ChOI.'ll>prO!
0UjU MIllO' Wrox.Prolll'A6985.ChOI._
Help
Creational Patterns
Creational patterns make applications less dependent on the vagaries of simplistic object construction
and class referencing. They provide a more flexible approach towards the four W s of object creation -
Who, What, Where, and When.
17
Chapter 1
Two of the creational patterns we discuss - Abstract Factory and Factory Method - exemplify the
subtlety and difficulty of properly applying patterns. Their names are similar, and fundamentally they
do the same thing - they both create objects. However, it's how each pattern achieves its task that makes
all the difference. Abstract Factory uses objects to manage object creation, while Factory Method relies
on class inheritance to create the right object.
The GoF cataloged five creational patterns: Abstract Factory, Builder, Factory Method, Prototype, and
Singleton. We'll be covering the Singleton, Abstract Factory, and Factory Method patterns.
GoF Intent: Ensure a clas only ha one instance, and provide a global point of access to it.
The most humble of patterns, Singleton ensures that an application creates exactly one instance of the
class in question. One classic application of Singleton is the management of scarce database connections
- this was particularly true before the advent of built-in pooling. Many other applications are still
relevant today - including the management of printer objects and TCP/IP connection objects.
In the old days of Visual Basic 6.0 and earlier, VB did not support explicit object creation. Instead, VB
hid object creation and developers were usually forced to control object creation with the aid of class
events and global variables. With the advent of VB.NET, the days of implicit object creation are gone.
We now have an accessible New constructor method, and this means that we can employ the Singleton
pattern in our VB.NET code.
In fact, the introduction of the default constructor into VB.NET is more than an object-oriented
nicety. One leading cause ofVB6 bugs was the fact that developers could not always control object
creation. In particular, problems arose when declaring a variable using the New keyword, like this:
Dim objSomeObject As New SomeObject
In such circumstances, the developer could never be certain if or when the Visual Basic runtime
engine instantiated the object.
Singleton is so simple that a diagram doesn't help to explain it. The mechanics are straightforward:
To emphasize the importance of applying design patterns accurately, let me recount a little story. A
programmer once implemented his own Singleton-like pattern by ignoring Step 3 and using the
default constructor instead. The idea made sense, and to a point, it worked. Only one problem -
each execution ofNew meant that a second instance of the class would be created!
The moral ofthe story is that you should think twice before reinventing the wheel. One ofthe benefits of
using an existing design pattern is that its consequences are known and documented. As soon as you
change the specification ofthe design pattern, you can no longer be sure ofthe behavior and consequences.
18
Introduction to Design Patterns
An Example
Here's an example of a class called MySingleton, which is implemented using the Singleton design
pattern. The default constructor, New (), has been hidden (by making it Private). The Shared
member, ffi_Instance, represents the single shared instance of the object, and the public function
Getlnstance () returns the object reference (but only creates it if it doesn't already exist):
, Public property
Public ReadOn l y Property TimeOfBirth() As String
Get
Return m_TimeOfBirth
End Get
End Property
End Class
Just because New is not publicly unavailable, this doesn't mean we don't need to create a MySingleton
object instance. The trick is to make sure that Getlnstance only creates it when the object does not exist!
Here's a little routine to show the design pattern in action. We create two object variables, objTestl
and objTest2, and use our public Getlnstance () method to instantiate them:
Sub Main ()
Dim objTestl As MySingleton
Dim objTest2 As MySingleton
Dim i As Integer
, call GetInstance()
objTestl = MySingleton.GetInstance()
Console . WriteLine('GetInstance() called at " &
Now . ToLongTimeSt r ing & " ; " &
"objTestl . TimeOfBirth() =" &
objTestl . TimeOfBirth())
19
Chapter 1
, wait a while
For i = 1 To 500000000
Next
Of course, we can't use the New constructor to create them, because it sprivate. Ifyou try using code
like this:
When you run this example, you should get output like this:
What does this show? First, there's only one Creating Singleton ... line, which shows that during the
course of this execution, the private New () constructor only runs once - so only one instance is created.
The subsequent lines show that the two object variables objTestl and objTest2 are references to the
same singleton object - the one that was created the first time Getlnstance () was called.
20
Introduction to Design Patterns
End I f
~utex.ReleaseMutex()
Return mLlnstance
End Function
, Public property
Public ReadOnly Property TimeOfBirth() As String
Get
Return m_TimeOfBirth
End Get
End Property
End Class
GoF Intent: Provide an interface for creating familie of related or dependent object
without specifying their concrete classe .
Suppose we have to write an interactive storybook application, which tells the story about a family of
three bears - Daddy Bear, Mommy Bear, and Baby Bear. Suppose also that the program must also be
able to tell this story using one of two bear families - either golden bears or brown bears. (Users ask for
the strangest things.) Of course, we will not know which family to use for the story until run time; some
users like to hear the story told with brown bears, others prefer to hear it told with golden bears.
Our application will need to create three objects in the implementation of this storybook application -
either GoldenDadBear, GoldenMomBear, GoldenBabyBear or BrownDadBear, BrownMomBear,
BrownBabyBear. What is the best, most flexible way for our code to instantiate all of the necessary
bear objects, based on the user's choice of "golden" or "brown"? This far-fetched design requirement
occurs more frequently than you might imagine, and matches the Abstract Factory design pattern.
A classic application ofAbstract Factory involves the creation ofentire families of GUJ widgets. Ifyou
ever build an application running on Windows and some future Linux-based shell, then you just might
need to manage the creation of toolbars, textboxes, dialog boxes, etc, based on the choice of operating
system. Here, as in our bear story application, the Abstract Factory pattern provides the solution.
21
Chapter 1
I am not going to rant about the evils and dangers of relying on global variables, because I have used
them too. Despite the honored membership of the global variable in the Spaghetti Code Club, the
fact is that VB6 developers were often hard-pressed to find a more efficient alternative.
Aside from the reliance on global variables, and the many Select Case statements now littering the
application, more significant problems could surface after the first release of the application. For
example, maybe we forgot that obj DadBear really came in three flavors, not two . And how easy is it to
keep those little changes in the BrownBabyBear class synchronized with its
GoldenBabyBear counterpart?
Let's look at the UML for our solution, based on the Abstract Family pattern. It might be easier to
appreciate this pattern if you think of it in two parts - the "bear creation managers" and the "bear
implementers". In our storybook application, the three BearFactory classes (on the left) serve as the
object creation managers. The other classes implement the bears:
. ..
Bear Implementers
1 D';'" 1
r--:-- - .- ,
BearFactory I : I
+CreateDadBear() I : I
+CreateMomBear() I : I
I : I
+CreateBabyBear()
I : I
? I
I
I
:
:
I
I
I
I I I
GoldenBearFactory . I . I
____
+CreateDadBear() -------Ji'
~ _L_~ : ~
I -: 1
+CreateMomBear() : 1 : I
+CreateBabyBearO BrownBea rFactory . I : I
: &1';''' 1 ::
+CreateDadBear() :-T'- - - - - - - - - - - - - - - - - - - - - -"":-1
Bear Creation Managers +CreateMomBearO
+CreateBabyBearO
I : 1
I : 1
I : I
I . I
I I
I I
Let's see how this translates into code. We'll start by building the bear creation managers. First, here's
the BearFactory interface:
22
Introduction to Design Patterns
Next, we use this to build the two bear creation managers, GoldenBearFactory and
BrownBearFactory:
The colon (:) notation in the first line of this class is a line continuation character. The VB.NET
engine expects the Inheri ts BearFactory clause to be on a new line, like this:
Public Class GoldenBearFactory
Inherits BearFactory
I just prefer using the colon line continuation character - it makes the inheritance relation more obvious.
Now, we'll construct the bear implementers. We will use interfaces again, to ensure that all of our bear
family members act accordingly. For example, the interface BabyBear guarantees that
BrownBabyBear and GoldenBabyBear are good kids:
23
Chapter 1
Having created the generic DadBear, MomBear, and BabyBear classes, we can describe the specific
Golden and Brown specializations that inherit from these classes. Here are the GoldenDadBear and
BrownDadBear classes that inherit from DadBear:
In order to keep the example simple, we've made these classes very small. We'll need four more classes
for GoldenMomBear, BrownMomBear, GoldenBabyBear, and BrownBabyBear:
24
Introduction to Design Patterns
It is worth noting how any Abstract Factory pattern rests on the strategic application of interfaces. It is
through interfaces that all of our "Bear Creation Managers" communicate with all of the "Bear
Implementation" classes.
Now we can write a little routine to test this. We'll use a simple message box to ask the user whether
they want to create a family of golden bears or a family of brown bears. The result is captured in the
object variable obj GoldenPreferred (which evaluates to either DialogResul t. Yes or
DialogResult .No):
Sub Main()
Dim objBearFactory As BearFactory
Dim objDadBear As DadBear
Dim objMomBear As MomBear
Dim objBabyBear As BabyBear
Dim objGoldenPreferred As DialogResult
Then we use the value of objGoldenPreferred to create the appropriate BearFactory object:
Finally, we can use the following generic code to create DadBear, MomBear, and BabyBear objects.
This code will use the BearFactory object selected above, and hence create members of the desired
bear family:
The object constructors report to the console at the time they are executed, noting the object type being
created. So, when you run this application you should see a message box like this:
Yes No
25
Chapter 1
If you click Yes, then the application will go ahead and tell the story using golden bears. You'll see this
output at the console:
GoldenDadBear Created
GoldenMomBear Created
GoldenBabyBear Created
If you click No, then the application will tell the story using brown bears, and you'll see this output at
the console instead:
BrownDadBear Created
BrownMomBear Created
BrownBabyBear Created
We had to create a foundation of 12 classes in order to be able to write such a generic piece of code in
the Main () routine. But with that foundation in place, the application as a whole is immensely scalable
and extensible. Abstract Factory not only manages existing families of objects, but also easily handles
the addition of new families.
However, there is one caveat. The constraining influence of the BearFactory class means that if you
create a new family, it must look very much like the existing families. If you wanted to add a new bear
family with teenagers, then things would get a little more complicated - it can't be done using the
Abstract Factory pattern alone. In fact, you might save the situation by using the Abstract Factory
pattern in conjunction with the Adapter pattern - but that discussion is for another time ...
GoF Intent: Define an interface for creating an object, but let subclasses decide which
cla to instantiate. Factory Method let a cia defer instantiation to ubcla se .
Don't blink when watching Factory Method in action for the first time. If you do, you stand a good
chance of missing the subtlety of its magic. The underlying premise is rather simple. A common
requirement in applications is for an object factory class that creates an array of similar objects, like this:
26
Introduction to Design Patterns
This is a perfectly functional class, up to a point. However, what happens when we want to adapt this
object factory to create the Dwarf objects in a different order? Or when we want the object factory to
create a different set of Dwarf objects? Using the model above, we would be forced to revisit the
Dwarf Factory itself and re-code it.
We can achieve a much more flexible situation by applying Factory Method. Here, we replace the
default constructor, New ( ), with our own custom constructor method, AddDwarfs ( ) :
Now, the array of Dwarf objects is Protected, rather than Private - thus, any object that inherits
from Dwarf Factory has access to the array. Just as significantly, the AddDwarfs () constructor
method is Overridable, which means that an inheriting object can implement its own AddDwarfs ()
constructor method.
It is not possible to make New () overridable, and this is another reason why the
InflexibleDwarfFactory class really is so infleXible.
So let's use our Dwarf Factory class to build an application to illustrate its newfound flexibility. We
haven't created the Dwarf class yet, so let's do that next. This simple class contains an implementation
of the default constructor, New ( ) , which sets the dwarfs name. It also has a read-only Name property.
All of our fairy tales will need this little helper class:
27
Chapter 1
We'll write a little application that tells two stories: first, it tells the story of Snow White (which, as we all
know, features seven dwarfs). Then, it will tell a new story, Snow White II The Sequel, in which Dopey
travels to visit his Scottish cousins Morag and Murdo. For the second story, we'll create a new object
factory based on Dwarf Factory, like this:
Sub Main()
Dim obj SnowWhiteO\>/arfFactory As New Dwarf Factory ()
objSnowWhiteDwarfFactory.AddDwarfs()
objSnowWhiteDwarfFactory . ShowDwarfs()
MessageBox.Show("Click OK to end')
End Sub
When you run the application, you should see the following output. Admittedly, the plot of these two
stories is not strong, but you can see that the character list is different:
28
Introduction to Design Patterns
Created by SnowWhiteIIDwarfFactory:
Dopey the Dwarf
Cousin Morag the Dwarf
Cousin Murdo the Dwarf
Thus, although we have added a little complexity in the way the Dwarf objects are created (inserting an
extra constructor method in addition to the existing constructor), we have gained flexibility by
encapsulating object creation without encumbering the default constructor. In fact, this feature is
invaluable in situations when the superclass's default constructor is more complex than that of the
Dwarf Factory constructor. For example, what if the Dwarf Factory constructor included a user
authentication mechnaism? Would you (or could you) include that logic in your new constructor?
Some programmers consider Factory Method to be a default coding style. Indeed, many developers feel
that the ability to take explicit control of object creation is so important that it should never be left
sitting in the middle of some arbitrary method. The power and flexibility gained by taking control via
Factory Method (and indeed Abstract Factory) are quite significant, as we've seen here.
At this point, we will leave the subject of creational patterns, and move on to look at some structural patterns.
Structural Patterns
Structural patterns govern how objects and classes work together. The most common feature of these
patterns is that they all work by inheritance. Each pattern applies the principles of inheritance in quite
different ways to accomplish its ends. Some patterns, like Adapter, apply inheritance with incredible
simplicity, while others require a little coffee and serious thought.
Before we go crazy with inheritance, it s worth noting a warning expressed by the GoP in relation
to the question of object inheritance versus object composition. In brief, they expressed a strong
preference for composition when faced with a choice between it and inheritance. Ifyou ever built an
application relying on a superciass that someone changed without your knowledge, then you
probably have an idea why they said that!
The GoF cataloged seven structural patterns: Adapter, Bridge, Composite, Decorator, Fa~ade,
Flyweight, and Proxy. We'll cover all but Flyweight here.
GoF Intent for Adapter: Convert the interface of a class into another interface clients
expect. Adapter lets cla e work together that couldn't otherwise because of incompatible
interfaces.
The purpose of the Adapter pattern is not ambitious. It is designed simply to adapt the interface of a
class so that it is compatible with the client that needs to use it. This requirement may be as trivial as
changing method names to fit your application's conventions.
29
Chapter 1
By contrast, the Fat;ade (pronounced "fa-sahd') pattern does a little more work. It creates a "fa~ade
class", which acts as a layer between the client and a set of service classes. The client then sends its
requests to an instance of the fa~ade class, which acts as an agent - manipulating the requests as
necessary and sending them on to the set of service classes. The purpose of the fa~ade class is to
eliminate the difficulties that the client would otherwise have in sending requests to a complex set of
service objects.
From these initial descriptions, it's rather difficult to tell these two patterns apart. Indeed, in practice
they can often be used interchangeably, because both patterns deal with the task of changing classes'
interfaces in order to make them easier for the client application to use.
However, as we'll see in the examples that follow, the structure of these two patterns is different, and
they do solve two subtly different problems. In particular, we'll include a UML diagram that describes
how the following two applications implement the two patterns - the difference between Adapter and
Fa~ade becomes clearer when you compare these two diagrams.
o A class that handles orders for a fast food restaurant. This class will be called
FastFoodOrderer, and we'll write it in-house.
o A class that handles orders for a fancy French restaurant.
However, at the time of the first release, the second of these classes will not be available to us. In fact,
this class is to be coded by a third party and we don't even know its interface yet. Therefore, the first
release of the application will only allow the user to order food from a certain no-frills fast food
restaurant. For the second release, we want to be able to adapt the third party class and insert it
seamlessly into the existing application.
In order to do this, the client application will have a single object called obj FoodOrderer, which is
capable of ordering both fast food and French food. Food will be ordered through the method
objFoodOrderer . Order (). Our FastFoodOrderer class will also have an Order () method. We
don't know whether the French restaurant class will have an Order () method, but it doesn't matter.
We'll design the application in such a way that we'll be able to adapt its interface to fit our application.
Here is the UML diagram for our application. It includes the implementation of the third-party class,
which (as it turns out) is called FrenchRestaurant, and has a method called OrderFromMenu ():
« interface»
FoodOrderer I FrenchRestaurant I
. . - The Adaptee
+Order() I +OrderFromMenuO I
l»
I
\/-,
,,
,, ,,
,
----, ,
,
: ,
LFastFoodOrderer I F
I renchFoodOrdererl
. - The Adapter
I +OrderO I I +OrderO J
30
Introduction to Design Patterns
This pattern allows us to use polymorphism in our client application to create an instance of a
FoodOrderer class, and use its Order () method. What happens next depends on what the user has
asked for:
o If the user is ordering French food, the application will use the implementation of Order ( )
provided by the FastFoodOrderer class.
o If the user is ordering fast food, the application will use the implementation of Order ( )
provided by the FrenchFoodOrderer class. This class is the adapter class - it adapts the
OrderFromMenu () method of the FrenchRestaurant class (the adaptee), allowing the
client application to use it indirectly.
Without this adapter/adaptee pattern, recoding our second release would be rather more difficult. In
order to facilitate calls to FrenchRestaurant, it might be possible to convert FoodOrderer to an
abstract class, perhaps add some new, specialized methods tcFrenchRestaurant. Either way, these
are rather less than desirable options.
Let's see how our application develops. First, here's the FoodOrderer interface:
Now, here's the FastFoodOrderer class that implements the FoodOrderer interface:
And here's the first version of the client application. It includes some simple test code in which we use
the FoodOrderer object to order some fast food:
Sub Main ()
Dim objFoodOrderer As FoodOrderer
MessageBox.Show("Click OK to end")
End Sub
When you run this, you can see (in the console output) that the FastFoodOrderer object has handled
the request for a cheeseburger:
After this first release, the third party delivers its implementation of the French restaurant class. This is
what they deliver:
31
Chapter 1
The rules of polymorphism won't allow the obj FoodOrderer object to be instantiated to type
FrenchRestaurant, because they're not related. So, we now build our FrenchFoodOrderer class:
The first line of the adapter class of the application, FrenchFoodOrderer, is quite busy - it inherits
and implements simultaneously. This is not an unusual 00 construction. It appears quite often within
the .NET Common Language Runtime (CLR) itself.
Now we can add some extra code to the client application, to demonstrate that objFoodOrderer is
indeed capable of ordering food from either establishment:
Sub Main()
Dim objFoodOrderer As FoodOrderer
MessageBox.Show("Click OK to end")
End Sub
While we've tried to avoid unnecessary code here, the main structure ofthe pattern is clear. We can
now use a similar technique to add more classes, which communicate orders to other restaurants. In
each case, we'd simply add the third-party object and an adapter object. In our application, the
obj FoodOrderer object would be able to assume the role of any of the adapter objects, and pass food
orders to any eaterie in town!
32
Introduction to Design Patterns
To solve this problem, we create a new class or interface that manages all the calls to the methods of the
three service classes. At the cost of one class, we will make it very easy for any developer to order some
food without navigating a bunch of some potentially complex interfaces!
_~ ~
Host
~ The "New ' interface
1-------;
+Ente rtai nGuestsO
Let's start at the top of our UML diagram with the three service classes. For the sake of brevity, we'll use
three simple service classes. You'll need to pretend that they have horribly complex interfaces:
33
Chapter 1
Now we'll write our fac;:ade class, which acts as an agent - making the use of these service objects very
easy for the client application:
objMealPreparer.CookFood(objSupermarketVisit.BuyFood(Entreel)
objCleaner.ClearTable()
objCleaner.WashDishes()
As you can see, the Host class performs all the necessary roles in one simple function call: buying the food,
preparing it and cleaning up afterwards. The interface for the Host class is much simpler than the combined
API of the three service objects, and this makes the code in the client application extremely simple:
Sub Main()
Dim objHost As New Host()
objHost.EntertainGuests("Pasta")
MessageBox.Show("Click OK to end')
End Sub
This is what you will see in the console window when you run this application:
Notice how all we had to do was call EntertainGuests () and the rest was all done for us. Much easier
than having to put in all those different calls every time our program wanted to throw a dinner party!
GoF Intent: Decouple an abstraction from its implementation 0 that the two can vary
independently.
34
Random documents with unrelated
content Scribd suggests to you:
Garuda to proceed (10). O king, before Nikumbha, unconquerable in
battle, could reach the city of Vajra, Pārtha and Krishna, the slayers
of their enemies, overtook him in the way (11). Beholding them the
highly powerful Pradyumna, the foremost of those conversant with
illusions, divided himself into three portions (12). On the other hand,
Nikumbha, like unto an immortal, smilingly fought with them all with
heavy clubs (13). Holding the maiden Bhānumati by his left hand,
the great Asura Nikumbha repeatedly hurled the club with his right
hand. Although thus assailed, Keshava, Kāma (Pradyumna) and
Arjuna, none, could strike him ruthlessly lest they might wound the
maiden (14-15). O king, although capable of slaying that
irrepressible enemy they began to sigh piteously out of their
excessive compassion for the maiden (16). As when a serpent gets
round a camel, a man, well up in the use of arms, strikes the
serpent leaving the camel to itself, so Pārtha, the foremost of
archers, began to strike the Daitya with his arrows (17). In
pursuance of the rules of art, their training and reasoning, Pārtha,
Kāma and Krishna did not strike the maiden but wounded the
Danavas with their cane-like arrows (18). Thereupon resorting to his
illusory powers Nikumbha so disappeared with the maiden from that
place that nobody could know it: Krishna, Kāma and Dhananjaya
however immediately pursued him: he, however, went on assuming
the semblance of a yellow vulture (19-20). Thereupon saving the
maiden, the heroic Dhananjaya assailed him again with cane-like
arrows piercing his very vitals (21). Thus pursued by those heroes
that great Asura, the slayer of his enemies, travelled all over the
earth consisting of seven insular continents and dropped down with
the maiden at last on the bank of the river Chela Gangā flowing on
the summit of the mount Gokarna (22–23). None amongst the gods,
Asuras or great ascetics could cross that mountain protected by the
energy of Mahadeva (24). Finding this weak point of Nikumbha, the
Bhaima chief Pradyumna, invincible in battle and quick coursing, got
hold of the maiden Bhānumati. And Krishna, and Arjuna began to
assail the Asura greatly with arrows. Then leaving the northern
range of the mount Gokarna, Nikumbha fled to the southern range.
Both the Krishnas however, riding on Garuda, pursued him (25–26).
Gradually the great Asura entered into Shatpura, the abode of his
kinsmen and those two heroes spent the night at the mouth of the
cave. With Krishna's permission the heroic son of Rukshmini
delightedly took Bhaima's daughter to the city of Dwārakā. And
keeping her there he returned to Shatpura, full of Dānavas and
beheld the two Krishnas of dreadful prowess at the mouth of the
cave (27-29). Thus occupying the entrance of the city of Shatpura
the highly powerful Krishna and Arjuna, desirous of slaying
Nikumbha, waited there with Pradyumna (30).
Thereupon desirous of fighting the highly powerful Nikumbha
came out of the cave, O king, no sooner he came out of the cave
than Dhananjaya, with arrows shot off his Gandiva bow, obstructed
the thorough-fair. In spite of it Nikumbha, the foremost of the
powerful, came out, took up his club covered with thorns and struck
Pārtha on his head (31–33). Thus assailed with that club Pritha's son
vomitted blood and lost his consciousness. The Asura, master of
illusions, smilingly struck the heroic son of Rukshmini, the foremost
of those conversant with illusions, who was waiting with his face
against him. Wounded on the head with that unseen stroke of the
club the heroic Pradyumna lost his consciousness. Beholding them
thus assailed and insensible Govinda, having Gada as his elder
brother, beside himself with anger, took up his club Koumodaki and
ran towards Nikumbha. Those two irrepressible heroes, roaring,
fought with each other (34–37). Riding his elephant Airāvata along
with the gods Sachi's Lord began to witness that dreadful combat
like unto the battle between the celestials and Asuras. Beholding the
gods Hrishikesha, the slayer of his enemies, tried to kill the Dānavas
in a wonderful battle, desirous of doing good unto the gods (38-39).
Whirling his Koumodaki, the large-armed Keshava, conversant with
military science, displayed many wondrous manoeuvres (40).
Nikumbha too, the foremost of Asuras, by virtue of his training
hurled his club, covered with many thorns, and displayed various
manoeuvres (41). At that time they fought like two roaring bulls for
a cow, two roaring elephants and two leopards worked up with
anger (42). O Bhārata, thereupon setting a highly dreadful shout,
he, with his club, set with eight bells, struck Krishna having Gada as
his elder brother. He too hurling his huge club threw it on
Nikumbha's head (43-44). At that time holding idle for a moment his
Koumodaki club the intelligent preceptor of the world, Hari fell down
insensible on earth (45). O king, while the high-souled Vasudeva was
reduced to this plight the whole world was filled with lamentations.
With the cool water of Mandākini mixed with ambrosia, the king of
gods himself sprinkled Keshava. O king, Krishna, the foremost of
gods, did so of his own accord, or else who can render the high-
souled Hari insensible?
O descendant of Bharata, thereupon regaining his
consciousness, Krishna, the slayer of his enemies, took up his discus
and asked the wicked Asura to bear it (49). At that time casting off
his body there the irrepressible Nikumbha, a great Māyāvin, went
away. Keshava however could not know it (50). Thinking that either
he was dead or on the point of death and remembering the
obligations of the heroes he did not strike him who was fallen.
Thereupon regaining their consciousness Pradyumna and Arjuna
came there and considering Nikumbha dead stood by Krishna (51-
52). Afterwards coming to know of the real truth Pradyumna,
conversant with illusions, said to Krishna:—"O father, the wicked
Nikumbha is not here. He has fled somewhere else" (53). No sooner
Pradyumna said this than Nikumbha's body disappeared. Seeing it
the powerful Lord, with Arjuna, laughed (54). O heroic king, few
minutes after they saw all over the earth and welkin thousands of
Nikumbha. The spectators also saw the heroic Krishna, Pārtha and
Rukshmini’s son in innumerable forms. It appeared indeed wonderful
(55–56). At that time amongst those great Asuras some held
Pārtha's bow, some his huge arrows, some his hands and some his
feet (57). Thus when the innumerable bodies of Pārtha were caught
the Asuras carried away the heroic Dhananjaya to the sky. Thus
when separated from Pārtha the heroic Krishna and his son pierced
Nikumbha with numerous shafts. Still they could not see his end.
One Nikumbha, divided into twain, became two. Thereupon seeing
every thing correctly by his celestial wisdom the Divine Lord Krishna,
the origin of the present and future and the slayer of Asuras, saw
the true form of Nikumbha, the creator of illusions and the stealer of
Dhananjaya. And before the presence of all creatures he, with his
discus, cut off his head (58–62.) O descendant of Bharata, when his
head was thus sundered that foremost of Asuras, leaving aside
Dhananjaya, fell down like an uprooted tree (63). O giver of honors,
at that time Pārtha was about to drop down from the sky. At
Krishna's mandate his son held him up (64). When Nikumbha thus
fell down on earth the deity Krishna consoled Keshava and with him
repaired to Dwarakā (65).
Having returned delightedly to Dwarakā the Lord Krishna, O
descendant of Yadu, and the foremost of Dāsharhas, saluted the
high-souled Narada (66). Thereupon the highly energetic Nārada
said to Bhānu:—"O descendant of Bhaima, do not consider yourself
insulted on account of your daughter being carried away (by
another). O Bhānu, listen to great cause hereof (67). O hero, on one
occasion while sporting in the garden of Raivata, this your daughter
excited the anger of the foremost of Munis Durvāsā who wrath fully
imprecated a curse on her saying:—'She is very much ill-mannered
and she must fall into the hands of an enemy.' At that time, myself
along with other Munis, propitiated him on behalf of your daughter
saying:—'Muni, O foremost of the pious, dost thou, informed of the
essence of religion as thou art, imprecate a curse on this innocent
girl who is observing her religious obligations? We request thee to
show favour into her' (68-70). O Bhaima chief, after we had said this
Durvāsā stood with his face down for a moment and then stricken
with compassion said:—'What I have said will prove true. It will
never be otherwise. Forsooth she will fall into the hands of an
enemy. Although thus fallen into the hands of an enemy she will not
be virtually contaminated; and she will obtain a beautiful husband,
will be lucky, a mother of many sons and mistress of immense
riches; this thin-built lady will always have beautiful fragrance
around her person, will always remain youthful and will forget the
sorrow consequent upon her being carried away by the enemy (71–
74)'. O hero, thus it had been pre-ordained so for Bhanumati before;
do you now confer her on Sahadeva for that son of Pandu is
virtuous, respectful and heroic (75)".
Thereupon regarding the words of Nārada, the virtuous souled
Bhāima gave away Bhāuumati to Madri's son Sahadeva (76). Having
sent an emissary Keshava, the holder of discus, had brought
Sahadeva there. After the wedding ceremony was over, he, with his
wife, returned to his own city. The man, who reverentially listens to
this conquest of Krishna or reads it, acquires success in every
business (77-78).
CHAPTER CCXXXVIII. THE DESTRUCTION OF
VAJRANABHA: AN ACCOUNT OF PRABHAVATI.
ebookgate.com