Refactoring existing code so that it improves and conforms to a design pattern can be a good thing. Your code will be easier to understand since it follows a known 'pattern'. Of course you have to need the change - your code will probably be uncomfortable to read and be crying out for clarification.
This refactoring is about implementing a one to many relationship in your code more clearly by refactoring to the Composite design pattern.
Here is the situation before and after the refactoring, in hand drawn UML.
The problem with the "before" situation is:
By refactoring, we remove the code duplication to a common base class.
The solution:
Here is a python example of the above refactoring.? Note that the display() method is actually called toPlainTextString() in this example.
?
# Before
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()
# After
class Node(object):
def __init__(self, name):
self.name = name
def toPlainTextString(self):
return self.name
class 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
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()
A proper refactoring means you don't break anything and everything behaves as before.
>python -u "before.py"
abc
xyz
>python -u "after.py"
abc
xyz
Confirmed - we get the same output in both cases. :-)
?