Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar...
Transcript of Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar...
![Page 1: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/1.jpg)
Produced by
Department of Computing, Maths & PhysicsWaterford Institute of Technology
http://www.wit.ie
http://elearning.wit.ie
Design Patterns
Eamonn de [email protected]
![Page 2: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/2.jpg)
Door/Light Example
Motivational Example for Observer Pattern
![Page 3: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/3.jpg)
Motivational Example• In an embedded system a Door opening should trigger a Light to turn on
• The Door closing should turn the light off
• Explore the structure of various designs by building a series of test cases
• Six versions:
• Version 0: No coupling between Door & Light
• Version 1: Couple Door & Light; Enable door to activate multiple lights
• Version 2: Introduce Cameras, to be also coupled to Door
• Version 3: Decouple Light & Camera from Door by refactoring to use Observer Pattern
• Version 4: Use java.util observer implementation
• Version 5: Anonymous inner class idiom
• Version 6: Lambda Idiom 3
![Page 4: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/4.jpg)
Version 0• Direct coupling between Door & Light
4
Class Diagram Communication Diagram
![Page 5: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/5.jpg)
@Test public void testOpenClose() { mainDoor.open(); overheadLight.turnOnLight(); sideLight.turnOnLight();
assertTrue(overheadLight.getLightState()); assertTrue(sideLight.getLightState()); mainDoor.close(); overheadLight.turnOffLight(); sideLight.turnOffLight(); assertFalse(overheadLight.getLightState()); assertFalse(sideLight.getLightState()); }}
0:Test
5
public class DoorTest{ private Door mainDoor; private Light overheadLight; private Light sideLight;
@Before public void setUp() throws Exception { mainDoor = new Door("Main Door"); overheadLight = new Light("Overhead Light"); sideLight = new Light("Side Light"); }
@After public void tearDown() throws Exception { mainDoor = null; overheadLight = null; sideLight = null; }
![Page 6: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/6.jpg)
public class Door{ private String name; private boolean isOpen;
public Door(String name) { this.name = name; isOpen = false; }
public void open() { if (isOpen == false) { System.out.println("Opening " + name); isOpen = true; } }
public void close() {
if (isOpen == true) { System.out.println("Closing " + name); isOpen = false; } }}
0:Door
• Door is not aware of Light class
6
![Page 7: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/7.jpg)
public class Light{ private String name; private boolean lightOn;
public Light(String nm) { name = nm; lightOn = false; }
public void turnOnLight() { if (!lightOn) { System.out.println("Turning on light" + name); lightOn = true; // activate light sensor } }
public void turnOffLight() { if (lightOn) { System.out.println("Turning Off light" + name); lightOn = false; // deactivate light sensor } }
public boolean getLightState() { return lightOn; }}
0:Light
• Light has no dependencies
7
![Page 8: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/8.jpg)
Version 1
• Couple Door & Light; Enable door to control multiple lights
8
![Page 9: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/9.jpg)
@Test public void testOpenClose() { mainDoor.addLight(overheadLight); mainDoor.addLight(sideLight);
mainDoor.open(); assertTrue(overheadLight.getLightState()); assertTrue(sideLight.getLightState());
mainDoor.close(); assertFalse(overheadLight.getLightState()); assertFalse(sideLight.getLightState());
mainDoor.open(); assertTrue(overheadLight.getLightState()); assertTrue(sideLight.getLightState()); }
1:TestDoor
9
public class DoorTest{ private Door mainDoor; private Light overheadLight; private Light sideLight;
@Before public void setUp() throws Exception { mainDoor = new Door("Main Door"); overheadLight = new Light("Overhead Light"); sideLight = new Light("Side Light"); }
@After public void tearDown() throws Exception { mainDoor = null; overheadLight = null; sideLight = null; }
![Page 10: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/10.jpg)
public class DoorTest{ private Door mainDoor; private Mockery context;
@Before public void setUp() throws Exception { mainDoor = new Door("Main Door"); context = new Mockery() {{ setImposteriser(ClassImposteriser.INSTANCE); }}; }
@Test public void testOpenCloseMock() { final Light light = context.mock(Light.class);
mainDoor.addLight(light); context.checking(new Expectations() {{ one(light).turnOnLight(); }}); mainDoor.open(); context.assertIsSatisfied(); context.checking(new Expectations() {{ one(light).turnOffLight(); }}); mainDoor.close(); context.assertIsSatisfied(); }
1:TestDoor - using JMock
• Use the JMock libraries to verify that open/closing the door triggers an on/off call to the light object.
10
![Page 11: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/11.jpg)
public class Door{ private String name; private boolean isOpen; private Collection<Light> lights;
public Door(String name) { this.name = name; isOpen = false; lights = new HashSet<Light>(); }
public void open() { if (isOpen == false) { System.out.println("Opening " + name); isOpen = true; turnOnLights(); } }
public void close() {
if (isOpen == true) { System.out.println("Closing " + name); isOpen = false; turnOffLights(); } }
1:Door
11
public void addLight(Light light) { lights.add(light); } private void turnOnLights() { for (Light light : lights) { light.turnOnLight(); } }
private void turnOffLights() { for (Light light : lights) { light.turnOffLight(); } }}
![Page 12: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/12.jpg)
public class Light{ private String name; private boolean lightOn;
public Light(String nm) { name = nm; lightOn = false; }
public void turnOnLight() { if (!lightOn) { System.out.println("Turning on light" + name); lightOn = true; // activate light sensor } }
public void turnOffLight() { if (lightOn) { System.out.println("Turning Off light" + name); lightOn = false; // deactivate light sensor } }
public boolean getLightState() { return lightOn; }}
1:Light
• No change from previous version
12
![Page 13: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/13.jpg)
Version 2: Introduce Camera
• Introduce Cameras, to be also coupled to Door
13
![Page 14: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/14.jpg)
2: Communication Diagram
14
![Page 15: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/15.jpg)
public class DoorTest{ private Door mainDoor; private Light light; private Camera camera; private Mockery context;
@Before public void setUp() throws Exception { context = new Mockery() {{ setImposteriser(ClassImposteriser.INSTANCE); }}; light = context.mock(Light.class); camera = context.mock(Camera.class); mainDoor = new Door("Main Door"); mainDoor.addLight(light); mainDoor.addCamera(camera); }
@After public void tearDown() throws Exception { mainDoor = null; }
2:TestDoor
15
@Test public void testOpenCloseMock() { context.checking(new Expectations() {{ one(light).turnOnLight(); one(camera).turnOnCamera(); }});
mainDoor.open(); context.assertIsSatisfied(); context.checking(new Expectations() {{ one(light).turnOffLight(); one(camera).turnOffCamera(); }}); mainDoor.close(); context.assertIsSatisfied(); }}
![Page 16: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/16.jpg)
public class Door{ private String name; private boolean isOpen; private Collection<Light> lights; Collection<Camera> cameras;
public Door(String name) { this.name = name; isOpen = false; lights = new HashSet<Light>(); cameras = new HashSet<Camera>(); }
... public void addCamera(Camera camera) { cameras.add(camera); }
public void open() { if (isOpen == false) { System.out.println("Opening " + name); isOpen = true; turnOnLights(); turnOnCameras(); } }
...
2:Door
16
...
private void turnOnCameras() { for (Camera camera : cameras) { camera.turnOnCamera(); } }
private void turnOffCameras() {
for (Camera camera : cameras) { camera.turnOffCamera(); } }}
![Page 17: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/17.jpg)
public class Light{ private String name; private boolean lightOn;
public Light(String nm) { name = nm; lightOn = false; }
public void turnOnLight() { if (!lightOn) { System.out.println("Turning on light" + name); lightOn = true; // activate light sensor } }
public void turnOffLight() { if (lightOn) { System.out.println("Turning Off light" + name); lightOn = false; // deactivate light sensor } }
public boolean getLightState() { return lightOn; }}
3:Light
• No change from previous versions
17
![Page 18: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/18.jpg)
Version 3: Observer
• Decouple Light & Camera from Door by refactoring to use Observer Pattern
18
Observable Observer
![Page 19: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/19.jpg)
3: Communication Diagram
19
![Page 20: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/20.jpg)
public class DoorTest{ private Door mainDoor; private Light light; private Camera camera; ...
@Before public void setUp() throws Exception { ... mainDoor = new Door("Main Door"); mainDoor.addObserver(light); mainDoor.addObserver(camera); }
3:TestDoor
20
@Test public void testOpenCloseMock() { context.checking(new Expectations() {{ one(light).update(mainDoor, true); one(camera).update(mainDoor, true); }}); mainDoor.open(); context.assertIsSatisfied(); context.checking(new Expectations() {{ one(light).update(mainDoor, false); one(camera).update(mainDoor, false); }}); mainDoor.close(); context.assertIsSatisfied(); }}
![Page 21: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/21.jpg)
public interface Observer{ public void update(Observable ob, Object o);}
3:Observer & Observable
21
public class Observable{ protected Collection<Observer> observers;
public Observable() {
observers = new HashSet<Observer>(); }
public void addObserver(Observer light) { observers.add(light); }
public void notifyObservers(Object o) { for (Observer observer : observers) { observer.update(this, o); } }}
![Page 22: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/22.jpg)
public class Door extends Observable{ private String name; private boolean isOpen;
public Door(String name) { this.name = name; isOpen = false; }
public void open() { if (isOpen == false) { System.out.println("Opening " + name); isOpen = true; notifyObservers(isOpen); } }
public void close() { if (isOpen == true) { System.out.println("Closing " + name); isOpen = false; notifyObservers(isOpen); } }}
3:Door
• Door is significantly simplified.
• All dependency management is handled in the Observable base class.
22
![Page 23: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/23.jpg)
public class Camera implements Observer{ private String name; private boolean cameraOn;
public Camera(String nm) { name = nm; cameraOn = false; }
public void update(Observable ob, Object o) { Boolean doorStatus = (Boolean) o;
if (doorStatus == true) { turnOnCamera(); } else { turnOffCamera(); } } public boolean getCameraState() { return cameraOn; }}
3:Camera (Light similar)
23
public void turnOnCamera() { if (!cameraOn) { System.out.println("Turning on camera " + name); cameraOn = true; // activate light sensor } }
public void turnOffCamera() {
if (cameraOn) { System.out.println("Turning Off camera " + name); cameraOn = false; // deactivate light sensor } }
![Page 24: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/24.jpg)
4:Java.util Observer Implementation
24
Observer Observable
![Page 25: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/25.jpg)
public class Door extends Observable{...}
4:Door, Light & Camera
25
public class Light implements Observer{...}
public class Camera implements Observer{...}
![Page 26: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/26.jpg)
@Test public void demonstrateAnonymousInnerClass() { mainDoor.addObserver(new Observer() { public void update(Observable obs, Object o) { Boolean open = (Boolean) o;
if (open == true) { System.out.println("main Door opening"); } else { System.out.println("main Door closing"); } } }); }
5: Anonymous Inner Class Idiom
• With Observe implementations in Java, it is common to implement the observer inline.
• This is called an “Anonymous Inner Class”.
• In the example here, a new Observer implementation is being created, and the single required method provided, all within the parameter list to the addObserver() method.
• Can be difficult to read - but extremely common, particularly in GUI code.
26
![Page 27: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/27.jpg)
@Test public void demonstrateLambda() { Observer observer = (Observable obs, Object o) -> { Boolean open = (Boolean) o; if (open == true) { System.out.println("main Door opening"); } else { System.out.println("main Door closing"); } };
mainDoor.addObserver(observer); mainDoor.open(); }
6: Lambda Idiom
• More elegant replacement for Anonymous inner class
27
![Page 28: Design Patterns - edeleastar-portfolio.github.io...Design Patterns Eamonn de Leastar edeleastar@wit.ie. Door/Light Example Motivational Example for Observer Pattern. Motivational Example](https://reader034.fdocuments.in/reader034/viewer/2022042413/5f2dc7cc71b1a45a730674ac/html5/thumbnails/28.jpg)
Except where otherwise noted, this content is licensed under a Creative Commons Attribution-NonCommercial 3.0 License.
For more information, please see http://creativecommons.org/licenses/by-nc/3.0/