lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

oo-design-patterns.wiki (12191B)


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