DesignPatterns
Assignment 8 - Design Patterns
- Will - Singleton and Mediator Patterns
- More here...
Daniel Gabriel
- Facade Pattern: The wikipedia article for this design pattern can be found here. Basically, a facade pattern is used to further abstract and encapsulate libraries and APIs for the sake of ease of the programmers. A Facade will provide a uniform interface to those libraries for the other classes in the program. In relation to game design, this can be very useful. A Facade for any graphical library or sound library could be made to make the creation and manipulation of game object much simpler.
The sample code given on the wikipedia page is:
import java.text.*; import java.util.*;
class UserfriendlyDate {
Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); public UserfriendlyDate (String isodate_ymd) throws ParseException { Date date = sdf.parse(isodate_ymd); cal.setTime(date); } public void addDays (int days) { cal.add (Calendar. DAY_OF_MONTH, days); } public String toString() { return sdf.format(cal.getTime()); }
}
class FacadePattern {
public static void main(String[] args) throws ParseException { UserfriendlyDate d = new UserfriendlyDate("1980-08-20"); System.out.println ("Date: " + d.toString()); d.addDays(20); System.out.println ("20 days after: " + d.toString()); }
}
- Reactor Pattern: The wikipedia article for this design pattern can be found here. A reactor pattern is used for handling service requests made of a program. It takes requests which may be asynchronous and deals with them in a synchronous manner. The usage of a Reactor Pattern would probably not be in a game, but rather a scheduling program or an operating system. The reactor pattern runs best on a single threaded program but can be modified to run in a multi-threaded environment. However, similar methods could be used in a game to handle incomming input from multiple synchronous sources and asynchronous sources (eg: a multiplayer game over a network).
Ryan
- Decorator Pattern: The decorator pattern can be utilized for applications where different combinations of what would normally be classes are needed. For example, take a program that creates a window. Next, you want to be able to create a window that can scroll vertically and horizontally depending on the page's content. Without using a design pattern one would have to construct an inheritance hierarchy of classes that extend the window class. More specifically, a vertical_scroll_bar class and a horizontal_scroll_bar class would have to be created. In addition, let's say that you would like to be able to add a boarder to the window which would require yet another class. Obviously, there are a number of combinations of window types that could occur, for instance a bordered window, or a bordered window that scrolls vertically, etc... Furthermore, notice that creating classes in this way is adding behavior to the application at compile time. Using the decorator pattern, behavior is added during runtime and thus is an alternative to subclassing as described above. The important difference to understand is that this pattern becomes quite useful when there are several different way of extending the functionality of an application. Using the aforementioned window example, a separate class would have to be made for each combination of window types. In contrast, decorators are objects created at runtime which can be combined on a peruse basis. The following code snippet show cases the decorators functionality in terms of the window example.
// the Window interface interface Window { public void draw(); // draws the Window public String getDescription(); // returns a description of the Window } // implementation of a simple Window without any scrollbars class SimpleWindow implements Window { public void draw() { // draw window } public String getDescription() { return "simple window"; } }
The following classes contain the decorators for all Window classes, including the decorator classes themselves..
// abstract decorator class - note that it implements Window abstract class WindowDecorator implements Window { protected Window decoratedWindow; // the Window being decorated public WindowDecorator (Window decoratedWindow) { this.decoratedWindow = decoratedWindow; } } // the first concrete decorator which adds vertical scrollbar functionality class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } public void draw() { drawVerticalScrollBar(); decoratedWindow.draw(); } private void drawVerticalScrollBar() { // draw the vertical scrollbar } public String getDescription() { return decoratedWindow.getDescription() + ", including vertical scrollbars"; } } // the second concrete decorator which adds horizontal scrollbar functionality class HorizontalScrollBarDecorator extends WindowDecorator { public HorizontalScrollBarDecorator (Window decoratedWindow) { super(decoratedWindow); } public void draw() { drawHorizontalScrollBar(); decoratedWindow.draw(); } private void drawHorizontalScrollBar() { // draw the horizontal scrollbar } public String getDescription() { return decoratedWindow.getDescription() + ", including horizontal scrollbars"; } }
Here's a test program that creates a Window instance which is fully decorated (i.e., with vertical and horizontal scrollbars), and prints its description:
public class DecoratedWindowTest { public static void main(String[] args) { // create a decorated Window with horizontal and vertical scrollbars Window decoratedWindow = new HorizontalScrollBarDecorator ( new VerticalScrollBarDecorator(new SimpleWindow())); // print the Window's description System.out.println(decoratedWindow.getDescription()); } }
The output of this program is "simple window, including vertical scrollbars, including horizontal scrollbars". Notice how the getDescription method of the two decorators first retrieve the decorated Window's description and "decorates" it with a suffix.
Code snippets taken from the wikipedia page on the Decorator Pattern.
Visitor Pattern:
The visitor pattern can be utilized to add operations to objects without modifying the class structure by separating an algorithm from the object. To employ the visitor pattern each class must contain an accept method which takes a visitor as a parameter. This method contains a call to the Visitor interface's visit method which will perform the desired operation. In addition, this pattern specifies how iteration over the object structure occurs. Various ways of iterating through the structures exists. For example, when an object's accept method executes it calls the visit method and passes the visitor object. The following example illustrates a use of the visitor pattern.
interface Visitor { void visit(Wheel wheel); void visit(Engine engine); void visit(Body body); void visit(Car car); } interface Visitable { void accept(Visitor visitor); } class Wheel implements Visitable { private String name; Wheel(String name) { this.name = name; } String getName() { return this.name; } public void accept(Visitor visitor) { visitor.visit(this); } } class Engine implements Visitable{ public void accept(Visitor visitor) { visitor.visit(this); } } class Body implements Visitable{ public void accept(Visitor visitor) { visitor.visit(this); } } class Car implements Visitable { private Engine engine = new Engine(); private Body body = new Body(); private Wheel[] wheels = { new Wheel("front left"), new Wheel("front right"), new Wheel("back left") , new Wheel("back right") }; public Engine getEngine() { return this.engine; } public Body getBody() { return this.body; } public Wheel[] getWheels() { return this.wheels; } public void accept(Visitor visitor) { visitor.visit(this); engine.accept(visitor); body.accept(visitor); for(int i = 0; i < wheels.length; i++) { Wheel wheel = wheels[i]; wheel.accept(visitor); } } } class PrintVisitor implements Visitor { public void visit(Wheel wheel) { System.out.println("Visiting "+ wheel.getName() + " wheel"); } public void visit(Engine engine) { System.out.println("Visiting engine"); } public void visit(Body body) { System.out.println("Visiting body"); } public void visit(Car car) { System.out.println("Visiting car"); } } class DoVisitor implements Visitor { public void visit(Wheel wheel) { System.out.println("Steering my wheel"); } public void visit(Engine engine) { System.out.println("Starting my engine"); } public void visit(Body body) { System.out.println("Moving my body"); } public void visit(Car car) { System.out.println("Vroom!"); } } public class VisitorDemo { static public void main(String[] args){ Car car = new Car(); Visitor visitor = new PrintVisitor(); Visitor doVisitor = new DoVisitor(); car.accept(visitor); car.accept(doVisitor); } }
Here an object of the Car class is created along with visitors that either 'visit' the specified portion of the car or perform an action at the specified portion of the car. Notice how through one call to each visitor all of the parts of the car are visited and each part of the car is utilized.
Since my game is still in the early stages of conceptual development it is difficult to say whether or not these patterns would be useful in the design.
Code snippets taken from the wikipedia page on the Visitor Pattern.
Matt O
- Object Pool
An object pool is a collection of objects that new objects can be taken from and unneeded ones
returned to. This cuts down on the time spent to create and destroy objects. This can drastically improve performance if you creating and destroying objects frequently.
This website has a good explanation of object pools and a generic object pool using an abstract
class (code here)as well as an example implementation of it (code here).
This pattern would be useful in a game for anything that would be continuously created and
destroyed, such as an enemy.
- Monitor
A monitor is used to synchronize access to some resource. It can be used to protect a hardware
resource or some data shared by different threads or process (like in a producer/consumer problem).
Java contains an abstract class called Monitor, which you can implement to make use of this.
The API is here.
I am honestly not sure how useful this would be for making a game.
Jim - Threadpool Pattern and Flyweight Pattern
Flyweight - This design pattern is useful when there is a need for many objects to exist that share some information. For example, the bouncing balls program that is in the java text book could be re-written to use the flyweight pattern. Each ball is an instance of the same object. The balls each share a image of the ball, radius, color, and movement functions. With the flyweight pattern each instance of the ball would only have to know where it is. The rest of the information would be stored in the flyweight class for the balls.
Benefits - Reduces the number of object instances at runtime, saving memory.
Centralizes state for many virtual ovjects into a sincle location.
Drawback - Once implemented, single instances of a class will not be able to behave independantly from other instances
Code - http://www.cs.uml.edu/~jdalphon/SE
Threadpool - This design pattern a number of threads are created to perform a number of tasks. Usually these tasks are organized in a queue. Typically, there are many more tasks than threads. As soon as a thread completes its task, it will request the next task from the queue until all tasks have been completed. The thread can then terminate, or sleep until there are new tasks available.
Benefits - Number of threads is variable so threads can be created and destroyed.
Drawback - Having a large threadpool means increased resource usage. threadpool
• Observer Pattern – Justin C.
o The observer pattern involves the creation of listener objects (objects that are on watch for events) and their subsequent attachment to a subject that will enact a given behavior as a result of the triggering event.
o Action listeners are the most common example of observers – relying on predefined (or easily definable) keyboard and mouse events as well as other input device events.
o Observers are the basis of event-driven programming – a methodology in which certain occurrences (events) trigger the execution of code and/or other events.
/* File Name : EventSource.java */
package OBS; import java.util.Observable; //Observable is here import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;
public class EventSource extends Observable implements Runnable {
public void run() { try { final InputStreamReader isr = new InputStreamReader( System.in ); final BufferedReader br = new BufferedReader( isr ); while( true ) { final String response = br.readLine(); setChanged(); notifyObservers( response ); } } catch (IOException e) { e.printStackTrace(); } }
} /* File Name: ResponseHandler.java */
package OBS;
import java.util.Observable; import java.util.Observer; /* this is Event Handler */
public class ResponseHandler implements Observer {
private String resp; public void update (Observable obj, Object arg) { if (arg instanceof String) { resp = (String) arg; System.out.println("\nReceived Response: "+ resp ); } }
} /* Filename : myapp.java */ /* This is main program */
package OBS;
public class myapp {
public static void main(String args[]) { System.out.println("Enter Text >"); // create an event source - reads from stdin final EventSource evSrc = new EventSource(); // create an observer final ResponseHandler respHandler = new ResponseHandler(); // subscribe the observer to the event source evSrc.addObserver( respHandler ); // run the program evSrc.run(); }
}
• Proxy Pattern – Justin C.
o The proxy pattern is defined as the use of a proxy class to abstractly reference another object usually external to the program (often to provide some measure of security).
o A proxy class is used as an interface to the external object the main program wishes to make use of, such as an unorganized section of memory, an organized file structure, a remote computer, an entire network connection, etc.
o The example below shows how a proxy pattern can be used as a place-holder for file access. Instead of loading the image as the program runs, the proxy merely holds the place of the image incase it is ever needed.
import java.util.*;
interface Image {
public void displayImage();
}
class RealImage implements Image {
private String filename; public RealImage(String filename) { this.filename = filename; System.out.println("Loading "+filename); } public void displayImage() { System.out.println("Displaying "+filename); }
}
class ProxyImage implements Image {
private String filename; private Image image; public ProxyImage(String filename) { this.filename = filename; } public void displayImage() { if (image == null) { image = new RealImage(filename); // load only on demand } image.displayImage(); }
}
class ProxyExample {
public static void main(String[] args) { List<Image> images = new ArrayList<Image>(); images.add( new ProxyImage("HiRes_10MB_Photo1") ); images.add( new ProxyImage("HiRes_10MB_Photo2") ); images.add( new ProxyImage("HiRes_10MB_Photo3") ); images.get(0).displayImage(); // loading necessary images.get(1).displayImage(); // loading necessary images.get(0).displayImage(); // no loading necessary; already done // the third image will never be loaded - time saved! }
}
Jonah Choquette
- Factory Pattern (see link for code examples): Specifically, it is a class or method that explicitly that creates
new objects without having to be told which class to be instanciated. The benefits of such methods are the creation of constructor methods that can have specific names
that detail their function, or encapsulation of multiple class types which share similar purposes and methods (image files, music files, polygon types, etc). However
there are some drawbacks to this pattern, as any change to the factory class may require code changes wherever its methods were used, and the factory method
makes extending or inheriting the factory method difficult or impossible depending on implementation and the code language environment being used.
Tor
- Command Pattern - Design a program to use classes to represent commands. Each instance of a caommand is represented by its own object.
// Imaginary example of a command object used with a text editor
class EditorCommandInterface { public: virtual void execute(TextEditor& context) = 0; virtual ~EditorCommandInterface() { } }; class CutCommand : public EditorCommandInterface { public: virtual void execute(TextEditor& context) { string s = context.GetSelectedText(); context.DeleteRange(context.GetSelectStart(), context.GetSelectEnd()); Clipboard.Copy(s); } };
I could use the command pattern in the supervisor interface, for adding image and sound files or selecting options before the game starts. Could also be used to control piece movement, threading commands to control sequential or simultaneous movement.
- Strategy Pattern - Use interfaces to implement algorithms, so algorithms can be interchanged on-the-fly as needed.
package wikipedia.patterns.strategy;
// MainApp test application class MainApp {
public static void main(String[] args) { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.execute(); context = new Context(new ConcreteStrategyB()); context.execute(); context = new Context(new ConcreteStrategyC()); context.execute(); } } // The classes that implement a concrete strategy should implement this // The context class uses this to call the concrete strategy interface IStrategy { void execute(); } // Implements the algorithm using the strategy interface class ConcreteStrategyA implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyA.execute()" ); } } class ConcreteStrategyB implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyB.execute()" ); } } class ConcreteStrategyC implements IStrategy { public void execute() { System.out.println( "Called ConcreteStrategyC.execute()" ); } } // Configured with a ConcreteStrategy object and maintains a reference to a Strategy object class Context { IStrategy strategy; // Constructor public Context(IStrategy strategy) { this.strategy = strategy; } public void execute() { strategy.execute(); }
I could use this when cutting up the picture into individual puzzle pieces, each algorithm would create a different edge shape. It could also be useful to control sounds, changing the algorithms if the mute button is toggled.
Jeff Anonymous method
This is an example of using an interface to create an anonymous method for passing a method to another method, in example what I have done for buttons.
config.createButton("Softball",new bg_method() { public int method() { //System.out.println("Switching to Softballs"); BouncyUniverse.setRadius(20); BouncyUniverse.setTexture("Softball.jpg"); return 0; } } , false); public void createButton(String label, bg_method method, boolean isThread) { JButton temp = new JButton(label); buttons.add(new ButtonContainer(temp,method,isThread)); this.add(temp); temp.setEnabled(true); temp.setActionCommand(label); temp.addActionListener(this); } public void actionPerformed(ActionEvent button) { // TODO Auto-generated method stub for (ButtonContainer b : buttons) { if (button.getActionCommand().compareTo(b.button.getActionCommand()) == 0) { if (b.isThread) { Background temp = new Background(b.method, 5); } else b.method.method(); } } } public interface bg_method { public int method(); } public class ButtonContainer { public JButton button; public bg_method method; public boolean isThread; public ButtonContainer(String label,bg_method method, boolean isThread) { button = new JButton(label); this.method = method; this.isThread = isThread; } public ButtonContainer(JButton button, bg_method method, boolean isThread) { this.button = button; this.method = method; this.isThread = isThread; } }