Professional Design Patterns in VB NET Building Adaptable Applications 1st Edition Tom Fischer pdf download
Professional Design Patterns in VB NET Building Adaptable Applications 1st Edition Tom Fischer pdf download
https://ebookgate.com/product/professional-design-patterns-in-vb-
net-building-adaptable-applications-1st-edition-tom-fischer/
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 info@apress.com, 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 atjcslater@hotmail.com.
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
Another Random Document on
Scribd Without Any Related Topics
For reading, Agathokles.
For rhapsody, Miltiades.
For playing lyre with fingers, Xenon.
For playing lyre, Kleoites.
Long Distance Race (varied from
2¼ miles to about ¾ mile).
Boys Asklepiades.
Junior epheboi Dionusios.
Middle ” Timokles.
Senior ” Moschion.
Men ” Aischrion.
Wrestling.
Boys Athenikon.
Junior epheboi Demetrios.
Middle ” Moschos.
Senior ” Theodotos.
Men ” Apellas.
Boxing.
Boys Herakleides.
(The rest is wanting.)
(Notice the three victories of the boy
Athenikon.)
At Thespiai in Boiotia[166] there were prizes for senior and junior
boys in the various races, and in boxing, wrestling, pankration, and
pentathlon, besides open prizes for poetry and music of all kinds.
Attic inscriptions arrange the events thus[167]:—
Stadion.
Junior Boys.
Middle Boys.
Senior Boys.
Boys Open.
Men.
Diaulos.
Junior Boys.
Middle Boys.
Senior Boys.
Boys Open.
Men.
Olympia.
Boys. Stadion (Pind. Ol. xiv.).
Boxing (Pind. Ol. x., xi.).
Wrestling (Pind. Ol. viii.).
(only in 628 B.C.) Pentathlon.
(not till 200 B.C.) Pankration.
Pythia.
Boys. Long Distance Race.
Diaulos (400 yards) (Pind. Puth. x.).
Stadion (200 yards) (Pind. Puth. xi.).
Boxing.
Wrestling (Bacchul. xi.).
Pankration (not till 346 B.C.).
But at Nemea both pentathlon[168] and pankration[169] for boys had
already been established by Pindar’s time, as well as the more usual
contests.[170]
How far individual schoolmasters, as distinct from the State, gave
prizes to their pupils, is little known; an epigram in the Anthology
supplies the only evidence, by narrating that “Konnaros received
eighty knucklebones because he wrote beautifully, better than the
other boys.”[171] But probably as a general rule the task of rewarding
merit was left to the public contests.
*****
Thus the State did much to encourage, if it did little to assist or
enforce, education. With such splendid rewards before them, boys
were probably quite eager to attend school, or at any rate the
palaistra. As soon as they were old enough to go to school,[172] they
were entrusted to an elderly slave,[173] who had to follow his master’s
boys about wherever they went and never let them go out of his
sight.[174] This was the paidagogos—a mixture of nurse, footman,
chaperon, and tutor—who is so prominent a figure on the vases and
in the literature of classical Hellas. There was only one for the family,
so that all the boys had to go about together and to attend the same
schools and the same palaistrai at the same time.[175] He waited on
them in the house, carried their books or lyres to school, sat and
watched them in the schoolroom, and kept a strict eye upon their
manners and morality in the streets and the gymnasia. Thus, for
instance, in Plato, Lusis and Menexenos have their paidagogoi in
attendance at the palaistra, who come and force them away from
the absorbing conversation of Sokrates, when it is time for them to
go home.[176] On a vase these attendants may be seen sitting on
stools behind their charges, in the schools of letters and music, with
long and suggestive canes in their hands.[177] A careful parent would,
of course, see that a slave who was to occupy so responsible a
position was worthy of it: but great carelessness seems often to
have been shown in this matter. The paidagogoi of Lusis and
Menexenos, boys of rank and position, had a bad accent, and on a
festival day, it is true, were slightly intoxicated.[178] Plutarch notices
that in his time parents often selected for this office slaves who were
of no use for any other purpose.[179] Xenophon, feeling the demerits
of the Athenian custom, commends the Spartans, who entrust the
boys not to slaves, but to public officials of the highest rank.[180] But
in well-regulated households the paidagogos was often a most
worthy and valuable servant. Sikinnos, who attended the children of
Themistokles in this capacity, was entrusted by his master with the
famous message to Xerxes, which brought on the battle of Salamis;
he was afterwards rewarded with his freedom, the citizenship of
Thespiai, and a substantial sum of money.[181] The custom of
employing these male-nurses dated back to early times at Athens:
for Solon made regulations about them.[182]
Boys were entrusted to paidagogoi as soon as they went to
school at six. This tutelage might last till the boy was eighteen[183]
and came of age; but more frequently it stopped earlier. Xenophon,
[184] in his wish to disparage everything not Spartan, declares that in
all other States the boys were set free from paidagogoi and
schoolmasters as soon as they became μειράκια, i.e. at about
fourteen or fifteen. The conjunction of schoolmasters suggests the
explanation of the variations in age. When an elder brother ceased
to attend school, and his younger brothers were still pursuing their
studies, there being only one paidagogos, he had to be left
unattended. But in cases where there was only one son, or where
the eldest of several stayed on at school until he came of age, he
would have the paidagogos to attend him until he was his own
master.
The life of such an attendant must have been an anxious one in
many cases. Plato compares his relations towards his charges with
the relations of an invalid towards his health: “He has to follow the
disease wherever it leads, being unable to cure it, and he spends his
life in perpetual anxiety with no time for anything else.”[185] With
unruly boys of different ages, and consequently of different tastes
and desires, the slave must have been often in a difficult position.
He had, however, the right of inflicting corporal punishment.
The chief object of the paidagogos was to safeguard the morals
of his charges. Boys were expected to be as modest and quiet in
their whole behaviour, and as carefully chaperoned, as young girls.
Parents told the schoolmasters to bestow much more attention upon
the boy’s behaviour than upon his letters and music.[186] This attitude
was characteristic of Athens from the first. The school laws of Solon,
as quoted by Aischines, deal wholly with morality. He gives the
following account of them[187]:—
“The old lawgivers stated expressly what sort of life the
free boy ought to lead and how he ought to be brought up;
they also dealt with the manners of lads and men of other
ages.” “In the case of the schoolmasters, to whom we are
compelled to entrust our children, although their livelihood
depends upon their good character, and bad behaviour is
ruinous to them, yet the lawgiver obviously distrusts them.
For he expressly states, first, the hour at which the free boy
ought to go to school; secondly, how many other boys are to
be present in the school; and then at what hour he is to
leave. He forbids the schoolmasters to open their schools and
the paidotribai their palaistrai before sunrise, and orders them
to close before sunset, being very suspicious of the empty
streets and of the darkness. Then he dealt with the boys who
attended schools, as to who they should be and of what
ages; and with the official who is to oversee these matters.
He dealt too with the regulation of the paidagogoi, and with
the festival of the Muses in the schools and of Hermes in the
palaistrai. Finally, he laid down regulations about the joint
attendance of the boys and the round of dithyrambic dances;
for he directed that the Choregos should be over forty.”
“No one over the age of boyhood might enter while the
boys were in school, except the son, brother, or son-in-law of
the master: the penalty of infringing this regulation was
death. At the festival of Hermes the person in charge of the
gymnasium[188] was not to allow any one over age to
accompany the boys in any way: unless he excluded such
persons from the gymnasium, he was to come under the law
of corrupting free boys.”
It will be noticed that these regulations are entirely concerned
with morality: they safeguard an existing system. They prescribe
neither the methods nor the subjects of education; for with such
matters the Athenian government did not interfere. But over the
question of morals it becomes unexpectedly tyrannous, and makes
the most minute regulations worthy of the strictest bureaucracy. It
interfered on this point in other ways also. The solemn council on
the Areiopagos had a special supervision over the young, from
Solon’s time onward; this was partially taken away from it by
Ephialtes and Perikles, but the Axiochos shows that, though in
abeyance, it continued to exist; in the middle of the fourth century,
however, Isokrates laments that it had fallen into disuse.
The Axiochos also states that the ten Sophronistai, elected to
guard the morals of the epheboi, exercised control over lads also.
These officials probably took their rise in the days of Solon: the
regulation that they must be over forty harmonises with the other
enactments of those days; and, although they died out at the end of
the fourth century, they were revived under the Roman Empire. Now
it is most unlikely that the archaistic legislators of imperial times
would have revived an office which had only existed during the
closing decades of the fourth century. Solon is known to have
appointed a magistracy specially to deal with the children;[189] and, if
these magistrates were not the Sophronistai, all trace of his creation
has been lost, which is most unlikely to have happened. So the
Sophronistai probably date from early times. Their duty was a
general supervision of the morals of the young; their chief function
would be to prosecute, on behalf of the State, parents and
schoolmasters who infringed Solon’s moral regulations. But such
prosecutions would usually be undertaken by private individuals
concerned in the case, and so this magistracy tended to become a
sinecure. It may even have ceased to exist after the fall of the
Areiopagos. But it seems to have revived under the restored
democracy for a while (if the Axiochos belongs to Aischines the
Sokratic), to sink again in the middle of the century. At the close of
the century it revives once more with the changes in the ephebic
system, and finally perishes when the epheboi became too few to
need ten officers to supervise their morals. An account of the
Sophronistai of this later period will be given in connection with the
epheboi.
PLATE II.
ebookgate.com