Mpg Dec07 Gian Lorenzetto

21
Encapsulate Composite with Builder Gian Lorenzetto

description

 

Transcript of Mpg Dec07 Gian Lorenzetto

Page 1: Mpg Dec07 Gian Lorenzetto

Encapsulate Composite with Builder

Gian Lorenzetto

Page 2: Mpg Dec07 Gian Lorenzetto

Recap ...

• Replace Implicit Tree with Composite (Refactoring to Patterns)

• Refactoring to Composite loosens coupling to implicit tree

• Builder loosens coupling to Composite

Page 3: Mpg Dec07 Gian Lorenzetto

Builder (Gof)

BuilderDiagram_1196754930587

1.1 of 2 2007.12.04 22:04:15

Page 4: Mpg Dec07 Gian Lorenzetto

Builder (GoF)• The construction of a complex object is separated from its

representation so that the same construction process can create different representations

• Builder Defines the required operations for creating various parts of a product

• ConcreteBuilder Implements the operations declared in the Builder interface.

• Director Builds a specific product via the interface exposed by the Builder object.

• Product The concrete type the Builder object creates.

Page 5: Mpg Dec07 Gian Lorenzetto

TagNode activityTag = new TagNode(“activity”);...TagNode flavorsTag = new TagNode(“flavors”);activityTag.add(favorsTag);

...TagNode flavorTag = new TagNode(“flavor”);flavorsTag.add(flavorTag);

Class Diagram 1_1196587101774

1.1 of 2 2007.12.03 21:30:50

Class Diagram 3_1196677789548

1.1 of 2 2007.12.03 21:41:27

TagBuilder builder = new TagBuilder(“activity”);...

builder.addChild(“flavors”);...

builder.addToParent(“flavors”, “flavor”);...

Page 6: Mpg Dec07 Gian Lorenzetto

Class Diagram 2_1196596929958

1.1 of 2 2007.12.03 21:20:31

Document doc = new DocumentImpl();Element orderTag = doc.createElement(“order”);orderTag.setAttribute(“id”, order.getOrderId());Element productTag = doc.createElement(“product”);productTag.setAttribute(“id”, product.getID());Text productName = doc.createTextNode(product.getName());productTag.appendChild(productName);orderTag.appendChld(productTag);

DOMBuilder orderBuilder = new DOMBuilder(“order”)orderBuilder.addAttribute(“id”, order.getOrder());orderBuilder.addChild(“product”);orderBuilder.addAttribute(“id”, product.getID());orderBuilder.adValue(product.getName());

Class Diagram 4_1196679481681

1.1 of 2 2007.12.03 22:05:38

Page 7: Mpg Dec07 Gian Lorenzetto

• Benefits

Simplifies a client’s code for constructing a Composite

Reduces the repetitive and error-prone nature of Composite creation

Creates a loose coupling between client and Composite

Allows for different representations of the encapsulated Composite or complex object

• Liabilities

May not have the most intention-revealing interface

Page 8: Mpg Dec07 Gian Lorenzetto

Mechanics1. Create Builder

2. Make Builder capable of creating children

3. Make Builder capable of setting attributes on nodes

4. Reflect on interface ... simplify

5. Refactor Composite construction code to use Builder

Page 9: Mpg Dec07 Gian Lorenzetto

TagNode RevisitedClass Diagram 5_1196681761272

1.1 of 2 2007.12.03 22:38:28

*

Composite interface ~ Builder interface

Page 10: Mpg Dec07 Gian Lorenzetto

Step 1.Create Builder

public class TagBuilderTest ...

public void testBuilderOneNode(){

String expectedXml = “<flavors/>”;String actualXml = TagBuilder(“flavors”).toXml();

assertXmlEquals(expectedXml, actualXml);}

Page 11: Mpg Dec07 Gian Lorenzetto

public class TagBuilder {

private TagNode rootNode;

public TagBuilder(String rootTagName){

rootNode = new TagNode(rootTagName);}

public String toXml(){

return rootNode.toString();}

}

Step 1.Create Builder

Page 12: Mpg Dec07 Gian Lorenzetto

Step 2.Support child creation and placement

public class TagBuilderTest ...

public void testBuilderOneChild(){

String expectedXml = “<flavors>” + “<flavor/>” + “</flavors>”;

TagBuilder builder = TagBuilder(“flavors”);builder.addChild(“flavor”);String actualXml = builder.toXml();

assertXmlEquals(expectedXml, actualXml);}

Page 13: Mpg Dec07 Gian Lorenzetto

Step 2.Support child creation and placement

public class TagBuilder {

private TagNode rootNode;private TagNode currentNode;

public TagBuilder(String rootTagName){

rootNode = new TagNode(rootTagName);currentNode = rootNode;

}

pubic void addChild(String childTagName){

TagNode parentNode = currentNode;currentNode = new TagNode(childTagName);parentNode.addChild(curentNode);

}

...

Page 14: Mpg Dec07 Gian Lorenzetto

Step 2.Support child creation and placement

public class TagBuilderTest ...

public void testBuilderOneChild(){

String expectedXml = “<flavors>” + “<flavor1/>” + “<flavor2/>” + “</flavors>”;

TagBuilder builder = TagBuilder(“flavors”);builder.addChild(“flavor1”);builder.addSibling(“flavor2”);String actualXml = builder.toXml();

assertXmlEquals(expectedXml, actualXml);}

Page 15: Mpg Dec07 Gian Lorenzetto

Step 2.Support child creation and placement

public class TagBuilder ...

pubic void addChild(String childTagName){

addTo(currentNode, childTagName);}

public void addSibling(String siblingTagName){

addTo(currentNode.getParent(), siblingTagName); }

private void addTo(TagNode parentNode, String tagName){

currentNode = new TagNode(tagName);parentNode.addChild(curentNode);

}...

1. Refactor Composite to support Builder2. Thirdparty Composite?

Page 16: Mpg Dec07 Gian Lorenzetto

Step 3.Support attributes and values

public class TagBuilderTest ...public void testAttributesAndVaues(){

String expectedXml = “<flavor name=ʼTest-Driven Developmentʼ>” + “<requirements>” + “<requirement type=ʼhardwareʼ>” + “1 computer for every 2 participants” + “</requirement>” “</requirements>” + “</flavor>”;

TagBuilder builder = TagBuilder(“flavor”);builder.addAttribute(“name”, “Test-Driven Development”);builder.addChild(“requirements”);builder.addToParent(“requirements”, “requirement”);builder.addAttribute(“type”, “hardware”);builder.addValue(“1 computer for every 2 participants”);String actualXml = builder.toXml();

assertXmlEquals(expectedXml, actualXml);}

Page 17: Mpg Dec07 Gian Lorenzetto

Step 3.Support attributes and values

public class TagBuilder ...

pubic void addAttribute(String name, String value){

currentNode.addAttribute(name, value);}

public void addValue(String value){

currentNode.addValue(value);}

...

Page 18: Mpg Dec07 Gian Lorenzetto

Step 4.Reflect ...

public class TagBuilder {

public TagBuilder(String rootTagName) { ... }

public void addChild(String childTagName) { ... }public void addSibling(String siblingTagName) { ... }public void addToParent(String parentTagName, String childTagName) { ... }

public void addAttribute(String name, String value) { ... }public void addValue(String value) { ... }

public String toXml() { ... }}

Page 19: Mpg Dec07 Gian Lorenzetto

public class TagBuilder {

public TagBuilder(String rootTagName) { ... }

public void addChild(String childTagName) { ... }public void addSibling(String siblingTagName) { ... }public void addToParent(String parentTagName, String childTagName) { ... }

public void addAttribute(String name, String value);public void addValue(String value);

public String toXml() { ... }}

public class TagNode{

public TagNode(String tagName) { ... }

public void add(TagNode childNode) { ... }

public void addAttribute(String name, String value) { ... }public void addValue(String value) { ... }

public String toString() { ... }}

Page 20: Mpg Dec07 Gian Lorenzetto

Step 5.Replace Composite construction codepublic class CatalogWriter ...

TagNode requirementsTag = new TagNode(“requirements”);flavorTag.add(requirementsTag);for (int i = 0; i < requirementsCount; ++i){

Requirement requirement = flavor.getRequirements()[i];TagNode requirementTag = new TagNode(“requirement”);...requirementsTag.add(requirementsTag);

}

public class CatalogWriter ...

builder.addChild(“requirements”);for (int i = 0; i < requirementsCount; ++i){

Requirement requirement = flavor.getRequirements()[i];builder.addToParent(“requirements”, “requirement”);...

}

Page 21: Mpg Dec07 Gian Lorenzetto

Questions?