Transcript

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

top related