Upload
melbournepatterns
View
1.189
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Citation preview
Andy BulkaTechnical DirectorAusthink Softwarewww.austhink.com
March 2008
Refactoring to patterns…
Simple Composite patternClass with a “children” collectionChildren are of type Node (i.e. you point to
yourself)
Classic Composite pattern (GOF)Distinguish
between Composites and Leaves
Benefit of “classic” is that you can distinguish leafs and override display() or doubleClick() or whatever for leafs.
The Problem CodeWe have two
classes that loop through their children – duplicate code
The children attribute is named differently in both classes – inconsistent
Both classes are “composites”
The SolutionCreate a common base class which has the
generic “composite” looping behaviourThat’s where the name of the refactoring
comes from “Extract Composite”
Original Problem code
class Node(object): def __init__(self, name): self.name = name def toPlainTextString(self): return self.name
class FormTag(Node): def __init__(self): self.allNodesVector = [] def toPlainTextString(self): result = "" for node in self.allNodesVector: result += node.toPlainTextString() return result
class LinkTag(Node): def __init__(self): self.linkData = [] def toPlainTextString(self): result = "" for node in self.linkData: result += node.toPlainTextString() return result
f = FormTag()f.allNodesVector.append(Node("a"))f.allNodesVector.append(Node("b"))f.allNodesVector.append(Node("c"))
l = LinkTag()l.linkData += [Node("x"), Node("y"), Node("z")]
print f.toPlainTextString()print l.toPlainTextString()
abcxyz
output
Step 1# Create a Composite Class - compile
class Composite(Node): pass
Step 2Make each child container (a class in the hierarchy
thatcontains duplicate child-handling code) a subclass ofyour composite – compile
class Composite(Node): pass
class FormTag(Composite): ….class LinkTag(Composite): ….
Step 3For each method with duplicated looping code 1. move & rename the child reference field UP to the composite using "Pull Up Field" 2. Move the method UP to the composite using
"Pull Up Method" 3. Pull up any relevant constructor code too.
Everything moved to Compositeclass Composite(Node): def __init__(self): self.children = [] def toPlainTextString(self): result = "" for node in self.children: result += node.toPlainTextString() return result
class FormTag(Composite): pass class LinkTag(Composite): pass
Step 4Check interfaces so that client code using the
old composites still works.
f = FormTag()f.children.append(Node("a"))f.children.append(Node("b"))f.children.append(Node("c"))
l = LinkTag()l.children += [Node("x"), Node("y"), Node("z")]
print f.toPlainTextString()print l.toPlainTextString()
f = FormTag()f.allNodesVector.append(Node("a"))f.allNodesVector.append(Node("b"))f.allNodesVector.append(Node("c"))
l = LinkTag()l.linkData += [Node("x"), Node("y"), Node("z")]
print f.toPlainTextString()print l.toPlainTextString()
New UMLWe have inserted a
new class called Composite above the LinkTag and FormTag, which does the common looping work.
Before and After