index.md (9092B)
1 +++ 2 title = 'Object-oriented design patterns in UML' 3 +++ 4 ## Object-oriented design patterns in UML 5 design pattern: a reusable form of solution to a common design problem (like a 'template') 6 7 not a finished design, cannot be transformed directly into source code 8 9 not prescriptive, so don't memorize them. it's important to understand when and why they're needed. 10 11 speaking of, they're not always needed. don't over-complicate shit, you'll end up with a dumpster fire that nobody can maintain. 12 13 essential parts of a design pattern 14 * Pattern name 15 * provides common vocab for software designers 16 * Intent 17 * What does the design pattern do? 18 * What is its rationale and intent? 19 * What design issue/problem does it address? 20 * Solution 21 * the basic elements providing solution to the problem (structure, participants, collaborations) 22 * Consequences 23 * results and trade offs by applying the pattern 24 25 ### Creational 26 how objects can be created (maintainability, control, extensibility) 27 28 we study the singleton and factory method. then there are also abstract factory, object pool, and prototype. 29 30 #### Singleton 31 <table> 32 <tr><th>Name</th><th>Singleton</th></tr> 33 <tr><td>Intent</td><td>To ensure that only one instance of a class is allowed in a system. <br>Controlled access to a single object is needed</td></tr> 34 <tr><td>Solution</td><td><img src="./singleton-solution-diagram.png">Singleton solution diagram</td></tr> 35 <tr><td>Consequences</td><td>Controlled access to sole instance <br> Reduced name space (fewer 'global' variables) <br> permits variable number of instances</td></tr> 36 </table> 37 38 Implementation 39 40 ```java 41 public class SingleObject { 42 // private constructor, cannot be instantiated from outside 43 private SingleObject(){} 44 45 // create the one single instance 46 private static SingleObject instance = new SingleObject(); 47 48 // get the only instance 49 public static SingleObject getInstance() { 50 return instance; 51 } 52 53 public void showMessage() { 54 System.out.println("Hello world!"); 55 } 56 ``` 57 58 #### Factory method 59 <table> 60 <tr><th>Name</th><th>Factory method</th></tr> 61 <tr><td>Intent</td><td>to abstract process of object creation so that type of created object can be determined at run time <br> to make design more customizable in terms of which objects can be created <br> avoiding the `new` operator because you don't want to hard code the class to be instantiated</td></tr> 62 <tr><td>Solution</td><td><img src="factory-method-diagram.png">Factory method diagram</td></tr> 63 <tr><td>Consequences</td><td>end up with dedicated class to create instances of objects <br> can pass arguments to the class to control the features of the objects</td></tr> 64 </table> 65 66 Implementation 67 68 ```java 69 public class ShapeFactory { 70 public Shape getShape(String shapeTYpe) { 71 if (shapeType == null) { 72 return null; 73 } 74 if (shapeType.equalsIgnoreCase("CIRCLE")) { 75 return new Circle(); 76 } 77 else if (shapeType.equalsIgnoreCase("RECTANGLE")) { 78 return new Rectangle(); 79 } 80 else if (shapeType.equalsIgnoreCase("SQUARE")) { 81 return new Square(); 82 } 83 84 return null; 85 } 86 } 87 ``` 88 89 ### Structural 90 how to form larger structures (management of complexity, efficiency) 91 92 adapter is studied in this course. also have proxy, bridge, decorator, facade, flyweight, composite, private class data. 93 94 #### Adapter 95 <table> 96 <tr><th>Name</th><th>Adapter</th></tr> 97 <tr><td>Intent</td><td>to convert interface of class into another interface <br> to let two or more classes with incompatible interfaces work together <br> to wrap an existing class with a new one <br> to have a kinda homogeneous interface that masks diversity of some set of various objects</td></tr> 98 <tr><td>Solution</td><td><img src="adapter-diagram-1.png">Adapter diagram 1 <img src="adapter-diagram-2.png">Adapter diagram 2</td></tr> 99 <tr><td>Consequences</td><td>single class is responsible to join functionalities of independent/incompatible classes</td></tr> 100 </table> 101 102 Implementation 103 104 ```java 105 public class Wrapper { 106 // the wrapped object 107 private LegacyComponent legacyComponent; 108 109 // constructor 110 public Wrapper (LegacyComponent instance) { 111 this.legacyComponent = instance; 112 } 113 114 // call to wrapped method 115 public int doThis() { 116 int result = 0; 117 float value = this.legacyComponent.doThat(); 118 // magic the value into an integer somehow, then 119 return result; 120 } 121 } 122 ``` 123 124 ### Behavioral 125 how responsibilities can be assigned to objects (objects decoupling, flexibility, better communication) 126 127 we study observer and chain of responsibility. there are also command, interpreter, iterator, mediator, memento, null object, state, strategy, template method, and visitor. 128 129 #### Observer 130 <table> 131 <tr><th>Name</th><th>Observer</th></tr> 132 <tr><td>Intent</td><td>to let some object(s) be notified of state changes in other objects in the system <br> when on object changes state, all dependents are notified and updated automatically</td></tr> 133 <tr><td>Solution</td><td><img src="observer-diagram.png">Observer diagram</td></tr> 134 <tr><td>Consequences</td><td>supports broadcast communication <br> state changes in object(s) should trigger behavior in other objects <br> you can reuse objects without reusing their observers and v-v. <br> you can remove observers without changing the subjects</td></tr> 135 </table> 136 137 Implementation 138 139 ```java 140 public abstract class Observer { 141 protected Subject subject; 142 public abstract void update(); 143 } 144 145 class MappingRover extends Observer { 146 // specify observed subject in constructor 147 public MappingRover(Subject subject) P 148 this.subject = subject; 149 subject.attach(this); 150 } 151 152 // observers "pull" information 153 public void update() { 154 if (this.subject.getState() == 0) { 155 // map the environment 156 } 157 else { 158 // "come back home", whatever that means 159 } 160 } 161 } 162 public abstract class Subject { 163 private List<Observer> observers = new ArrayList<Observer>(); 164 private int state; 165 166 public int getState() { ... } 167 public void setState(int state) { ... } // and notify all observers 168 public void attach(Observer observer) { ... } // add to observers list 169 public void detach(Observer observer) { ... } //remove from observers list 170 171 public void notifyAllObservers() { ... } // run the update function for each observer in list 172 } 173 174 public static void main(String[] args) { 175 CentralStation cs = new CentralStation(); 176 cs.setState(0); 177 178 MappingRover rover1 = new MappingRover(cs); 179 CameraRover rover2 = new CameraRover(cs); 180 CameraRover rover3 = new CameraRover(cs); 181 182 cs.setState(1); 183 } 184 ``` 185 186 #### Chain of responsibility 187 <table> 188 </tr><th>Name</th><th>Chain of responsibility</th></tr> 189 </tr><td>Intent</td><td>avoid coupling sender of request to receiver by giving more than one object a chance to handle request <br> chain receiving objects and pass request along chain until an object handles it (sequential)</td></tr> 190 </tr><td>Solution</td><td><img src="chain-of-responsibility-diagram.png">Chain of responsibility diagram</td></tr> 191 </tr><td>Consequences</td><td>Reduced coupling between objects (every object needs to know its successor) <br> handler(s) are not known a priori and a request might be unhandled <br> you can change responsibilities by changing chain at runtime</td></tr> 192 </table> 193 194 Implementation 195 196 ```java 197 public class Task { 198 private Coordinate coords; 199 private RequestEnum request; 200 201 // basic getters and setters 202 public Coordinate getcoords() { ... } 203 public setCoords(Coordinate coords) { ... } 204 205 public RequestEnum getRequest() { ... } 206 public setRequest(RequestEnum request) { ... } 207 } 208 209 public enum RequestEnum { 210 PICTURE, MAP; 211 } 212 213 public class Coordinate { 214 private float lat, lon; 215 216 // basic getters and setters 217 public float getLat() { ... }; 218 public setLat(float lat) { ... }; 219 public float getLon() { ... }; 220 public setLon(float lon) { ... }; 221 } 222 223 public abstract class TaskHandler { 224 TaskHandler successor; 225 publicc void setSuccessor(TaskHandler successor) { 226 this.successor = successor; 227 } 228 public abstract void handleRequest(Task task); 229 } 230 231 public class CameraRover extends TaskHandler { 232 public void handleRequest(Task task) { 233 if (task.request == RequestEnum.PICTURE) { 234 // take a picture 235 } 236 else { 237 // pass on to successor 238 if (successor != null) { 239 successor.handleRequest(request); 240 } 241 } 242 } 243 } 244 245 public class Main { 246 public static TaskHandler setUpChain() { 247 MapRover mapper = new MapRover(); 248 CameraRover photographer1 = new CameraRover(); 249 CameraRover photographer2 = new CameraRover(); 250 CameraRover photographer3 = new CameraRover(); 251 252 return mapper; 253 } 254 public static void main(Striing[] args) { 255 TaskHandler chain = setUpChain; 256 257 chain.handleRequest(...); 258 } 259 } 260 ``` 261