📄 tiofp documentation - building an abstract bom with the composite pattern.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0082)http://www.techinsite.com.au/tiOPF/Doc/4_BuildingAnAbstractBOMWithTheComposite.htm -->
<HTML><HEAD><TITLE>tiOFP Documentation - Building an abstract BOM with the composite pattern</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312"><!-- InstanceBegin template="/Templates/TechInsite_Template.dwt" codeOutsideHTMLIsLocked="false" --><!-- InstanceBeginEditable name="doctitle" --><!-- InstanceEndEditable --><!-- InstanceBeginEditable name="head" --><!-- InstanceEndEditable --><LINK
href="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/TechInsite.css"
type=text/css rel=stylesheet>
<META content="MSHTML 6.00.3790.1830" name=GENERATOR></HEAD>
<BODY>
<SCRIPT type=text/javascript>function Go(){return}</SCRIPT>
<SCRIPT
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/MainMenu_TechInsite.js"
type=text/javascript></SCRIPT>
<SCRIPT
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/HVMenu.js"
type=text/javascript></SCRIPT>
<NOSCRIPT>Your browser does not support script</NOSCRIPT>
<DIV id=Container><IMG height=75 alt=""
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/Banner01.jpg"
width=600 border=0>
<TABLE cellPadding=5 valign="middle">
<TBODY>
<TR>
<TD>
<DIV id=pageheader1>TechInsite</DIV></TD>
<TD>
<DIV id=pageheader2>Home of the TechInsite Object Persistence
Framework<BR>Melbourne, Australia</DIV></TD></TR></TBODY></TABLE>
<HR>
<TABLE>
<TBODY>
<TR>
<TD>
<DIV id=HMenu style="POSITION: relative"></DIV></TD></TR></TBODY></TABLE><BR>
<HR>
<!-- InstanceBeginEditable name="Page title" -->
<H1>4. Building an Abstract BOM with the Composite Pattern </H1><!-- InstanceEndEditable --><!-- InstanceBeginEditable name="Page body" -->
<H1 class=Normal>The aims of this section </H1>
<P>In the previous two chapters we investigated how the Visitor and Template
Method patterns can be used together to manage objects that are saved to either
a custom text file, or a relational database. In these chapters, we started to
develop an abstract collection class, and abstract business object class and we
will extend these classes, adding more of the functionality that will be
required in a complex business system.</P>
<H2>Prerequisites</H2>
<P>This chapter builds on the concepts introduced in chapter #2 ‘The Visitor
Framework’ so it will be a good idea to read this chapter first.</P>
<P>The business problem we will work with as an example</P>
<P>The previous business object model</P>
<P>We will continue to develop the contact management application, and will
extend the business object model to represent the data more realistically. In
the previous chapter, we created a TPerson class and its corresponding
collection class TPeople. This class diagram looked like this:</P>
<P><IMG height=89
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image001.gif"
width=275> </P>
<P>Rework the address book BOM to better represent the business domain</P>
<P>We shall do several things to improve this business object model. Firstly,
the properties that a TPerson can have shall be replaced by the more usual
LastName, FirstName, Title and Initials. Secondly, instead of each person only
being able to have one EMail address, we shall allow them to have a list of what
we will call E-Addresses. An E-Address shall be a one-line address that can
contain a phone number, fax number, email address or web URL. (The example
application ‘DemoTIPerFramework’ extends this model further so people can have
street or post office box addresses too.) The UML of the extended TPerson family
of classes looks like this:</P>
<P><IMG height=280
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image002.jpg"
width=427> </P>
<P>From this diagram we can see four classes:</P>
<TABLE cellSpacing=0 cellPadding=0>
<TBODY>
<TR class=Normal>
<TD vAlign=top width=111>
<P><STRONG>Class </STRONG></P></TD>
<TD vAlign=top width=479>
<P><STRONG>Description </STRONG></P></TD></TR>
<TR class=Normal>
<TD vAlign=top width=111>
<P>TPeople </P></TD>
<TD vAlign=top width=479>
<P>A list of TPerson(s). Descends from TPerVisList and implements list
management methods like GetItems( I ) : TPerson and Add( pData : TPerson )
</P></TD></TR>
<TR class=Normal>
<TD vAlign=top width=111>
<P>TPerson </P></TD>
<TD vAlign=top width=479>
<P>A person object that descends from TPerObjAbs. Owned by TPeople. Has
published properties for LastName, FirstName, Title and Initials. Has a
property EAdrsList that is of type TEAdrsList to hold a list of
E-Addresses. </P></TD></TR>
<TR class=Normal>
<TD vAlign=top width=111>
<P>TAdrsList </P></TD>
<TD vAlign=top width=479>
<P>A container for TEAdrs objects, descends from TPerVisList </P></TD></TR>
<TR class=Normal>
<TD vAlign=top width=111>
<P>TEAdrs </P></TD>
<TD vAlign=top width=479>
<P>An electronic address object that belong to the TPerson. Descends from
TPerObjAbs and has properties Address type and address text.
</P></TD></TR></TBODY></TABLE>
<P>We shall concentrate on implementing a useful abstract business object and
business object list first, then implement concrete classes towards the end of
this chapter. After we have implemented the class structure, we shall write some
helper functions that use the features in the abstract business objects to
output the class hierarchy as text for debugging, or to search a hierarchy for
an object with a given set of properties..</P>
<H2>The Composite pattern – what GoF say</H2>
<P>The intent of the Composite, as quoted from ‘Design Patterns’: Compose
objects into tree structures to represent whole-part hierarchies. Composite lets
clients treat individual objects and compositions of objects uniformly.</P>
<H2>Implementing the abstract business object model</H2>
<P>A type safe relationship between the collection and business objects</P>
<P>The first thing we shall do is to establish the relationship between the
abstract collection class and the abstract business object class. The Composite
pattern has introduced us to the idea of treating list objects and regular
business objects as the same type of class, so we shall continue with the idea
of the collection class descending from the business object class. The UML
representing the relationship, which we setup in a pervious chapter looks like
this:</P>
<P><IMG height=290
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image001_0000.gif"
width=346> </P>
<P>The Visitor – Visited relationship was discussed in chapter #2. Our abstract
persistent objects will descend from TVisited because we want to be able to pass
visitors over collections of objects with as little work as possible from the
programmer. We will be focusing on the relationship between TPerObjAbs and
TPerObjList next, but first we will add the list like behavior to
TPerObjList.</P>
<H2>Adding list behavior to TPerObjAbs</H2>
<P>The first question is what behavior should we be adding to TPerObjAbs to turn
it into a useful collection class? Delphi’s TList help text provides a good
starting point as it details the properties and methods of the TList class.
These are shown below:</P>
<TABLE cellSpacing=0 cellPadding=0>
<TBODY>
<TR>
<TD vAlign=top width=295>
<P align=center><STRONG>Properties </STRONG></P></TD>
<TD vAlign=top width=295>
<P align=center><STRONG>Methods </STRONG></P></TD></TR>
<TR>
<TD vAlign=top width=295>
<P align=center> </P>
<P align=center><IMG height=145
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image002_0000.jpg"
width=197></P></TD>
<TD vAlign=top width=295>
<P align=center> </P>
<P align=center><IMG height=320
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image004.jpg"
width=165></P></TD></TR></TBODY></TABLE>
<P>Of these, we will start by adding the properties Items and Count, and the
methods Add, Clear, Delete, First, IndexOf, Insert, Last and Remove. To make it
as easy as possible for developers who are new to the framework, we will give
the methods the same signature (or parameters and return type) as in Delphi’s
TList class, with one change: Where the TList takes a TObject or Pointer as a
parameter, we will substitute a TPerObjAbs. Here is the class diagram:</P>
<P><IMG height=224
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image001_0001.gif"
width=368> </P>
<P>The interface of TPerObjList is shown below:</P><PRE>TPerObjList = class( TPerObjAbs )
private
FList : TObjectList ;
function GetList: TList;
protected
function GetItems(pIndex: integer): TPerObjAbs; virtual ;
procedure SetItems(pIndex: integer; const Value: TPerObjAbs); virtual ;
function GetCount: integer; virtual;
public
// Constructor & Destructor
constructor Create ; override ;
destructor Destroy ; override ;
// Public properties
property List : TList read GetList ;
property Items[ pIndex : integer ] : TPerObjAbs read GetItems write SetItems ;
property Count : integer read GetCount ;
// Public methods
procedure Add( pData : TObject ) ; virtual ;
procedure Clear ; virtual ;
procedure Delete( pIndex : integer ) ; virtual ;
function First : TPerObjAbs ; virtual ;
function IndexOf( pData : TPerObjAbs ) : integer ; virtual ;
procedure Insert( pIndex : integer ; pData : TPerObjAbs ) ; virtual ;
function Last : TPerObjAbs ; virtual ;
procedure Remove( pData : TPerObjAbs ) ; virtual ;
// The Iterate method is still overridden here as we are using the code
// base we developed in the earlier chapter on the Visitor
procedure Iterate( pVisitor : TVisitor ) ; override ;
end ;</PRE>
<P>The implementation of TPerObjList is rather dull as each method simply
delegates the work to the owned TObjectList (with some type casting as
necessary) like this:</P><PRE>function TPerObjList.Last: TPerObjAbs;
begin
result := TPerObjAbs( FList.Last ) ;
end;</PRE>
<P>We shall add one extra property to TPerObjAbs called &quo;owner&quo;.
Owner will behave in much the same way that Delphi&quo;s TComponent.Owner
property behaves. When we add an object to a TPerObjList, we shall take the
opportunity to set its owner property as shown below:</P><PRE>procedure TPerObjList.Add(pData: TObject);
begin
FList.Add( pData ) ;
pData.Owner := Self ;
end;</PRE>
<P>The details of the relationship between TPerObjAbs and TPerObjList are shown
in the UML below.</P>
<P><IMG height=293
src="tiOFP Documentation - Building an abstract BOM with the composite pattern_files/4_BuildingAnAbstractBOMWithTheComposite_clip_image001_0002.gif"
width=421> </P>
<P>This diagram tells us 3 things.</P>
<OL>
<LI>TPerObjList inherits from TPerObjAbs. This means we can treat both classes
in the same way. This has significant benefits when we start building concrete
business classes.
<P></P>
<LI>TPerObjList maintains an internal list of TPerObjAbs. This list can
contain 0 or many instances of TPerObjAbs. The owned instances of TPerObjAbs
are indexed by the Items property.
<LI>TPerObjAbs has a property Owner of type TPerObjAbs. If a TPerObjList owns
an instance of TPerObjAbs, the owner property of the TPerObjAbs will have been
set to the instance of TPerObjList in its Add method. If a TPerObjAbs owns
another TPerObjAbs, the programmer will have to set the Owner property
manually in code. </LI></OL>
<P>The need to make the iterate method generic</P>
<P>Now that we have coded a firm relationship between TPerObjAbs and
TPerObjList, we can look at how to make the iterate method more generic. The
implementation of iterate that we developed in chapter #2 looks like this:</P><PRE>procedure TPerObjList.Iterate(pVisitor: TVisitor);
var
i : integer ;
begin
inherited Iterate( pVisitor ) ;
for i := 0 to FList.Count - 1 do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -