Design patterns =============== 1) What is a design pattern? 2) Can you give me an example? 3) Can I wake up and invent a new design pattern tomorrow? 4) Has anyone heard of GoF? - Design Patterns, Elements of Reusable Design, also called "The Gang of Four" 5) We have seen some design patterns in this course. Which ones? - Singleton, for the homework. - Iterator in the data-structures lesson. - Observer to separate the notificatin of events from the action in the implementation of a door. - State, to implement the turnstyle algorithm. - Bridge (?) to implement the reader-writer protocol. 6) Techniques that are design patterns in some languages are just built-in in others. Can you give me an example? - Exceptions: raise, catch, handle 7) Design patterns are divided into three categories. Which ones? - Criational patterns - Structural patterns - Behavioral patterns 8) What is each category all about? 9) Can you give me examples of patterns in each category? - Criational: factories, builders, prototypes, singletons. - Structural: adapters, bridges, composites, decorators, flyweights, facades, proxies. - Behavioral: observers, templates, visitors, states, commands, mediators, chains of responsabilities, interpreters, iterators. Example: implementing the items in the game "Trails of Alucubaca"? ================================================================== 10) What is the interface of a item? public interface Item { double getValue(); int getAge(); double getWeight(); int getHitPoints(); void setDamage(int damage); String getName(); String getDescription(); } 11) What would be an implementation of this interface? public class SimpleItem implements Item { private int age, hitPoints; private double weight; private String name, description; public SimpleItem(int initialHP, String name, String desc) { hitPoints = initialHP; this.name = name; description = desc; } public SimpleItem() { this(0, "", ""); } public int getAge() { return age; } public int getHitPoints() { return hitPoints; } public double getValue() { return 10.0 * hitPoints; } public double getWeight() { return weight; } public void setDamage(int damage) { if (damage > hitPoints) { hitPoints = 0; } else { hitPoints -= damage; } } public String getDescription() { return description; } public String getName() { return name; } } 12) How a diamond, which is something indivisible, would be implemented? public class Diamond extends SimpleItem { public Diamond(String desc) { super(1000, "Diamond", desc); } } 13) What is a composite item? import java.util.LinkedList; import java.util.List; public class CompositeItem extends SimpleItem { private List components; public CompositeItem(String name, String description) { super(0, name, description); components = new LinkedList(); } public void addItem(Item i) { components.add(i); } @Override public double getWeight() { double weight = 0.0; for (Item i : components) { weight += i.getWeight(); } return weight; } @Override public int getHitPoints() { int hp = 0; for (Item i : components) { hp += i.getHitPoints(); } return hp; } @Override public int getAge() { int maxAge = 0; for (Item i : components) { if (i.getAge() > maxAge) { maxAge = i.getAge(); } } return maxAge; } @Override public double getValue() { double value = 0.0; for (Item i : components) { value += i.getValue(); } return value; } @Override public void setDamage(int damage) { for (Item i : components) { i.setDamage(damage); } } } 14) This technique that we just saw is a design pattern called Composite. Can you provide a UML class diagram for this design of Items? 14.1) Are composites in which category of design pattern? 15) What is the key idea behind the composite pattern? 16) What are the advantages of using the composite pattern? What about the disadvantages? Does it hurts the ISP? 17) How is the code to create a composite item? public class Driver { public static void main(String args[]) { CompositeItem t = new CompositeItem("Treasure", "A box of jewels"); t.addItem(new Diamond("A glittering diamond")); CompositeItem c1 = new CompositeItem("Necklace", "The princess's necklace"); c1.addItem(new Chain("Chain of gold")); c1.addItem(new Ruby("The Tear of Blood")); c1.addItem(new Diamond("The glittering raindrop")); c1.addItem(new Diamond("The sparckling sun")); t.addItem(c1); t.addItem(new Diamond("The Sparkling Star")); System.out.println(t); } } 18) How to separate this creational code from the rest of the application logic? import composite.Item; public interface Builder { Item getItem(); } 19) What would be a typical implementation of a builder? public class NecklaceBuilder implements Builder { public Item getItem() { CompositeItem c1 = new CompositeItem("Necklace", "The princess's necklace"); c1.addItem(new Chain("Chain of gold")); c1.addItem(new Ruby("The Tear of Blood")); c1.addItem(new Diamond("The glittering raindrop")); c1.addItem(new Diamond("The sparckling sun")); return c1; } } 20) And how would this look like in the application code? public class Driver { public static void main(String[] args) { Item treasure = (new TreasureBuilder()).getItem(); System.out.println(treasure); } } 21) What are the problems with the Builder approach? 21.1) How could I count the number of items that have been created? 21.2) What about counting only the items created throw builders? 21.3) I am always creating a new builder. This puts some tension on the gargabe collector. Would it be possible to recycle the builders? public class BuilderFactory { private static NecklaceBuilder neckB = new NecklaceBuilder(); private static TreasureBuilder trsrB = new TreasureBuilder(); public Builder getBuilder(String bName) throws NoBuilderException { if (bName.equals("necklace")) { return neckB; } else if (bName.equals("treasure")) { return trsrB; } else { throw new NoBuilderException(bName + " is not a valid builder"); } } } 22) This is a factory. Which other things could we do with factories? 23) Let's imagine that the Trails of Alucubaca end up becoming popular. Which problems of scalability could we face? 24) How to solve these problems? 25) Which data are common among many items of the same kind? public interface Item { double getValue(); int getAge(); double getWeight(); int getHitPoints(); void setDamage(int damage); String getName(); String getDescription(); } 26) Can you separate these data into a single class? public class ItemQualifier { private String name, descriptions, weight; public ItemQualifier(String name2, String desc, double weight2) { name = name2; description = desc; weight = weight2; } public double getWeight() { return weight; } public String getDescription() { return description; } public String getName() { return name; } @Override public String toString() { return name + ", " + description + ", Weight = " + weight; } } 27) How to group these common data into a item qualifier when creating an item? import java.util.HashMap; import java.util.Map; public class SimpleItem implements Item { private static Map qualifiers = new HashMap(); private ItemQualifier iq; private int age; private int hitPoints; public static int numItemQualifiers() { return SimpleItem.qualifiers.keySet().size(); } public SimpleItem(int initialHP, double weight, String name, String desc) { hitPoints = initialHP; ItemQualifier iqAux = new ItemQualifier(name, desc, weight); if (SimpleItem.qualifiers.containsKey(iqAux.hashCode())) { iq = SimpleItem.qualifiers.get(iqAux.hashCode()); } else { iq = iqAux; SimpleItem.qualifiers.put(iqAux.hashCode(), iqAux); } } public SimpleItem() { this(0, 0.0, "", ""); } public int getAge() { return age; } public int getHitPoints() { return hitPoints; } public double getValue() { return 10.0 * hitPoints; } public double getWeight() { return iq.getWeight(); } public void setDamage(int damage) { if (damage > hitPoints) { hitPoints = 0; } else { hitPoints -= damage; } } public String getDescription() { return iq.getDescription(); } public String getName() { return iq.getName(); } public String toString() { return iq + ", HP = " + hitPoints + ", Age = " + age; } } 28) Is it possible that we have collisions inside the hash table? In case of collisions, what would happen? 29) It is necessary to distinguish one item qualifier from the other inside the hash table. How to do it? public class ItemQualifier { @Override public int hashCode() { return (int)weight + name.hashCode() + description.hashCode(); } @Override public boolean equals(Object o) { if (!(o instanceof ItemQualifier)) { return false; } else if (o == this) { return true; } else { ItemQualifier other = (ItemQualifier)o; return other.name.equals(name) && other.description.equals(description) && other.weight == weight; } } } 30) What is the key idea behind the Flyweight pattern?