design pattern qa
TRANSCRIPT
-
8/20/2019 Design Pattern QA
1/171
About Design Pattern
What is the design pattern?
If a problem occurs over and over again, a solution to that problem
has been used effectively. That solution is described as a pattern.
The design patterns are language-independent strategies for solving
common object-oriented design problems. When you make a
design, you should know the names of some common solutions.Learning design patterns is good for people to communicate each
other effectively. In fact, you may have been familiar with some
design patterns, you may not use well-known names to describe
them. SUN suggests GOF (Gang Of Four--four pioneer guys who
wrote a book named "Design Patterns"- Elements of Reusable
Object-Oriented Software), so we use that book as our guide to
describe solutions. Please make you be familiar with these termsand learn how other people solve the code problems.
Do I have to use the design pattern?
If you want to be a professional Java developer, you should know
at least some popular solutions to coding problems. Such solutions
have been proved efficient and effective by the experienced
developers. These solutions are described as so-called design
patterns. Learning design patterns speeds up your experience
accumulation in OOA/OOD. Once you grasped them, you would be
benefit from them for all your life and jump up yourselves to be a
master of designing and developing. Furthermore, you will be able
to use these terms to communicate with your fellows or assessors
more effectively.
-
8/20/2019 Design Pattern QA
2/171
Many programmers with many years experience don't know design
patterns, but as an Object-Oriented programmer, you have to know
them well, especially for new Java programmers. Actually, when
you solved a coding problem, you have used a design pattern. Youmay not use a popular name to describe it or may not choose an
effective way to better intellectually control over what you built.
Learning how the experienced developers to solve the coding
problems and trying to use them in your project are a best way to
earn your experience and certification.
Remember that learning the design patterns will really change how
you design your code; not only will you be smarter but will you
sound a lot smarter, too.
How many design patterns?
Many. A site says at least 250 existing patterns are used in OO
world, including Spaghetti which refers to poor coding habits. The
23 design patterns by GOF are well known, and more are to bediscovered on the way.
Note that the design patterns are not idioms or algorithms or
components.
What is the relationship among these patterns?
Generally, to build a system, you may need many patterns to fit
together. Different designer may use different patterns to solve the
same problem. Usually:
Some patterns naturally fit together
One pattern may lead to another
-
8/20/2019 Design Pattern QA
3/171
Some patterns are similar and alternative
Patterns are discoverable and documentable
Patterns are not methods or framework
Patterns give you hint to solve a problem effectively
Creational Patterns
a.
Abstract Factory
Definition
Provides one level of interface higher than the factory pattern. It is
used to return one of several factories.
Where to use & benefits Creates families of related or dependent objects like Kit.
Provides a class library of products, exposing interface not
implementation.
Needs to isolate concrete classes from their super classes.
A system needs independent of how its products are created,
composed, and represented. Try to enforce a constraint.
An alternative to Facade to hide platform-specific classes
Easily extensible to a system or a family
Related patterns include
o Factory method, which is often implemented with an
abstract factory.
-
8/20/2019 Design Pattern QA
4/171
o Singleton, which is often implemented with an abstract
factory.
o Prototype, which is often implemented with an abstract
factory.o Facade, which is often used with an abstract factory by
providing an interface for creating implementing class.
Example
Suppose you need to write a program to show data in two different
places. Let's say from a local or a remote database. You need to
make a connection to a database before working on the data. In this
case, you have two choices, local or remote. You may use abstract
factory design pattern to design the interface in the following way:
-
8/20/2019 Design Pattern QA
5/171
class DataInfo {}
interface Local {DataInfo[] loadDB(String filename);
}
interface Remote extends Local{void connect2WWW(String url);
}
class LocalMode implements Local {public DataInfo[] loadDB(String name) {
System.out.print("Load from a local database");
return null;}
}
class RemoteMode implements Remote {public void connect2WWW(String url) {
System.out.println("Connect to a remote site");}public DataInfo[] loadDB(String name) {
System.out.println("Load from a remotedatabase ");
return null;}
}
// The Abstract Factoryinterface ConnectionFactory {Local getLocalConnection();Remote getRemoteConnection();
}
class DataManager implements ConnectionFactory {
-
8/20/2019 Design Pattern QA
6/171
boolean local = false;DataInfo[] data;//...public Local getLocalConnection() {
return new LocalMode();}public Remote getRemoteConnection() {
return new RemoteMode();}public void loadData() {
if(local){Local conn = getLocalConnection();data = conn.loadDB("db.db");
}else {Remote conn = getRemoteConnection();
conn.connect2WWW("www.some.where.com");data = conn.loadDB("db.db");
}
}// work on data
public void setConnection(boolean b) {local = b;
}}
-
8/20/2019 Design Pattern QA
7/171
//Use the following Test class to test the aboveclassesclass Test {
public static void main(String[] args) {DataManager dm = new DataManager();DataInfo[] di = null;String dbFileName = "db.db";if (args.length == 1) {
//assume local is set to truedm.setConnection(true);
LocalMode lm =(LocalMode)dm.getLocalConnection();
di = lm.loadDB(dbFileName);} else {
//Note: dm.local = false is defaultsetting
RemoteMode rm =(RemoteMode)dm.getRemoteConnection();
rm.connect2WWW("www.javacamp.org/db/");di = rm.loadDB(dbFileName);
}//use one set of methods to deal with
loaded data.//You don't need to worry about connection
from this point.//Like di.find(), di.search() etc.
}}
C:\ Command Prompt
C:\> java TestConnect to a remote site
Load from a remote database
-
8/20/2019 Design Pattern QA
8/171
C:\ Command Prompt
C:\> java Test localLoad from a local database
Such design is often used in SCJD project assignment. If you have
a multiple places to load data, you just add more methods in the
connection interface without altering other structure, or add a
location variable in.
-
8/20/2019 Design Pattern QA
9/171
b.
Builder
Definition
Construct a complex object from simple objects step by step.
Where to use & benefits
Make a complex object by specifying only its type and
content. The built object is shielded from the details of itsconstruction.
Want to decouple the process of building a complex object
from the parts that make up the object.
Isolate code for construction and representation.
Give you finer control over the construction process.
Related patterns include
o Abstract Factory, which focuses on the layer over the
factory pattern (may be simple or complex), whereas a
builder pattern focuses on building a complex object from
other simple objects.
o Composite, which is often used to build a complex object.
Example
To build a house, we will take several steps:
1. build foundation,
2. build frame,
3. build exterior,
4. build interior.
-
8/20/2019 Design Pattern QA
10/171
Let's use an abstract class HouseBuilder to define these 4 steps.
Any subclass of HouseBuilder will follow these 4 steps to build
house (that is to say to implement these 4 methods in the subclass).
Then we use a WorkShop class to force the order of these 4 steps(that is to say that we have to build interior after having finished
first three steps). The TestBuilder class is used to test the
coordination of these classes and to check the building process.
import java.util.*;
class WorkShop {
//force the order of building processpublic void construct(HouseBuilder hb) {
hb.buildFoundation();hb.buildFrame();hb.buildExterior();hb.buildInterior();
}}
-
8/20/2019 Design Pattern QA
11/171
//set steps for building a houseabstract class HouseBuilder {
protected House house = new House();
protected String showProgress() {return house.toString();
}
abstract public void buildFoundation();abstract public void buildFrame();abstract public void buildExterior();abstract public void buildInterior();
}
class OneStoryHouse extends HouseBuilder {
public OneStoryHouse(String features) {house.setType(this.getClass() + " " +
features);}public void buildFoundation() {
//doEngineering()//doExcavating()//doPlumbingHeatingElectricity()//doSewerWaterHookUp()//doFoundationInspection()
house.setProgress("foundation is done");}
public void buildFrame() {//doHeatingPlumbingRoof()//doElectricityRoute()//doDoorsWindows()//doFrameInspection()
house.setProgress("frame is done");
-
8/20/2019 Design Pattern QA
12/171
}
public void buildExterior() {//doOverheadDoors()//doBrickWorks()//doSidingsoffitsGutters()//doDrivewayGarageFloor()//doDeckRail()//doLandScaping()house.setProgress("Exterior is done");
}
public void buildInterior() {//doAlarmPrewiring()//doBuiltinVacuum()//doInsulation()//doDryWall()//doPainting()//doLinoleum()//doCabinet()//doTileWork()//doLightFixtureBlinds()//doCleaning()//doInteriorInspection()house.setProgress("Interior is under
going");}
}
class TwoStoryHouse extends HouseBuilder {
public TwoStoryHouse(String features) {house.setType(this.getClass() + " " +
features);}
public void buildFoundation() {
-
8/20/2019 Design Pattern QA
13/171
//doEngineering()//doExcavating()//doPlumbingHeatingElectricity()//doSewerWaterHookUp()//doFoundationInspection()house.setProgress("foundation is done");
}
public void buildFrame() {//doHeatingPlumbingRoof()//doElectricityRoute()//doDoorsWindows()//doFrameInspection()house.setProgress("frame is under
construction");}
public void buildExterior() {//doOverheadDoors()//doBrickWorks()//doSidingsoffitsGutters()//doDrivewayGarageFloor()//doDeckRail()//doLandScaping()house.setProgress("Exterior is waiting to
start");}
public void buildInterior() {//doAlarmPrewiring()//doBuiltinVacuum()//doInsulation()//doDryWall()//doPainting()//doLinoleum()
//doCabinet()
-
8/20/2019 Design Pattern QA
14/171
//doTileWork()//doLightFixtureBlinds()//doCleaning()//doInteriorInspection()house.setProgress("Interior is not started
yet");}
}
class House {private String type = null;private List features = new ArrayList();
public House() {
}
public House(String type) {this.type = type;
}
-
8/20/2019 Design Pattern QA
15/171
public void setType(String type) {
this.type = type;}
public String getType() {return type;
}
public void setProgress(String s) {features.add(s);
}
public String toString() {StringBuffer ff = new StringBuffer();String t = type.substring(6);ff.append(t + "\n ");for (int i = 0; i < features.size(); i ++)
{ff.append(features.get(i) + "\n ");
}return ff.toString();
}}
class TestBuilder {
public static void main(String[] args) {
HouseBuilder one = new OneStoryHouse("2bedrooms, 2.5 baths, 2-car garage, 1500 sqft");
HouseBuilder two = new TwoStoryHouse("4bedrooms, 4 baths, 3-car garage, 5000 sqft");
WorkShop shop = new WorkShop();
shop.construct(one);
-
8/20/2019 Design Pattern QA
16/171
shop.construct(two);
System.out.println("Check house buildingprogress: \n");
System.out.println(one.showProgress());System.out.println(two.showProgress());
}}//need jdk1.5 above to compile
C:\ Command Prompt
C:\> javac TestBuilder.java
C:\> java TestBuilderCheck house building progress:
OneStoryHouse 2 bedrooms, 2.5baths, 2-car garage, 1500 sqftfoundation is doneframe is doneExterior is doneInterior is under going
TwoStoryHouse 4 bedrooms, 4 baths,3-car garage, 5000 sqftfoundation is doneframe is under constructionExterior is waiting to startInterior is not started yet
C:\>
-
8/20/2019 Design Pattern QA
17/171
To fine tune the above example, every do method can be designed
as a class. Similar functional class can be designed once and used
by other classes. e.g. Window, Door, Kitchen, etc.
Another example, such as writing a Pizza program. Every gradient
can be designed as a class. One pizza at least consists of several
gradients. Different pizza has different gradients. A builder pattern
may be adopted.
-
8/20/2019 Design Pattern QA
18/171
c.
Factory Method
Definition
Provides an abstraction or an interface and lets subclass or
implementing classes decide which class or method should be
instantiated or called, based on the conditions or parameters given.
Where to use & benefits
Connect parallel class hierarchies.
A class wants its subclasses to specify the object.
A class cannot anticipate its subclasses, which must be created.
A family of objects needs to be separated by using shared
interface.
The code needs to deal with interface, not implemented
classes. Hide concrete classes from the client.
Factory methods can be parameterized.
The returned object may be either abstract or concrete object.
Providing hooks for subclasses is more flexible than creating
objects directly.
Follow naming conventions to help other developers to
recognize the code structure. Related patterns include
o Abstract Factory , which is a layer higher than a factory
method.
o Template method, which defines a skeleton of an
algorithm to defer some steps to subclasses or avoid
subclasses
-
8/20/2019 Design Pattern QA
19/171
o Prototype, which creates a new object by copying an
instance, so it reduces subclasses.
o Singleton, which makes a returned factory method unique.
Examples
To illustrate such concept, let's use a simple example. To paint a
picture, you may need several steps. A shape is an interface.
Several implementing classes may be designed in the following
way.
interface Shape {public void draw();
}
class Line implements Shape {Point x, y;Line(Point a, Point b) {
x = a;
y = b;}public void draw() {
//draw a line;}
}
-
8/20/2019 Design Pattern QA
20/171
class Square implements Shape {Point start;int width, height;Square(Point s, int w, int h) {
start = s;width = w;height = h;
}public void draw() {
//draw a square;}
}class Circle implements Shape {
....}
class Painting {Point x, y;int width, height, radius;Painting(Point a, Point b, int w, int h, int r)
{x = a;y = b;width = w;height = h;radius = r;
}
Shape drawLine() {return new Line(x,y);}Shape drawSquare() {
return new Square(x, width, height);}Shape drawCircle() {
return new Circle(x, radius);
}
-
8/20/2019 Design Pattern QA
21/171
....}
...Shape pic;Painting pt;//initializing pt....if (line)
pic = pt.drawLine();if (square)
pic = pt.drawSquare();if (circle)
pic = pt.drawCircle();
From the above example, you may see that the Shape pic's type
depends on the condition given. The variable pic may be a line or
square or a circle.
You may use several constructors with different parameters to
instantiate the object you want. It is another way to design with
Factory pattern. For example,
-
8/20/2019 Design Pattern QA
22/171
class Painting {...Painting(Point a, Point b) {
new Line(a, b); //draw a line}Painting(Point a, int w, int h) {
new Square(a, w, h); //draw a square}Painting(Point a, int r){
new Circle(a, r); //draw a circle}...
}
You may use several methods to finish the drawing jobs. It is so-
called factory method pattern. for example,
class Painting {...Painting(Point a, Point b) {
draw(a, b); //draw a line}Painting(Point a, int w, int h) {
draw(a, w, h); //draw a square}Painting(Point a, int r){
draw(a, r); //draw a circle}
...}
The above draw() methods are overloaded.
Here is a popular example of Factory design pattern. For example,
you have several database storages located in several places. The
-
8/20/2019 Design Pattern QA
23/171
program working on the database is the same. The user may choose
local mode or remote mode. The condition is the choice by the user.
You may design your program with Factory pattern. When the local
mode is set, you may instantiate an object to work on the localdatabase. If the remote mode is set, you may instantiate an object
which may have more job to do like remote connection,
downloading, etc.
interface DatabaseService {public DataInfo getDataInfo() throws
Exception;
public FieldInfo getFieldInfo() throwsException;
public void write(FieldInfo fi) throwsException;
public void modify(FieldInfo fi) throwsException;
public void delete(FieldInfo fi) throwsException;
//...}class Data implements DatabaseService {
public Data(String fileName) {...};public Data(URL url, String fileName) {....};public DataInfo getDataInfo() throws Exception
{...};public FieldInfo getFieldInfo() throws
Exception {...};public void write(FieldInfo fi) throws
Exception {...};public void modify(FieldInfo fi) throws
Exception {...};public void delete(FieldInfo fi) throws
Exception {...};}class DataManager{
-
8/20/2019 Design Pattern QA
24/171
Data data = null;...if (local) {
data = new Data(localFile);...
}if (remote){
data = new Data(connectRemote,databaseFile);
...}data.write(someInfo);data.modify(someInfo);....
}
To illustrate how to use factory design pattern with class level
implementation, here is a real world example. A company has a
website to display testing result from a plain text file. Recently, thecompany purchased a new machine which produces a binary data
file, another new machine on the way, it is possible that one will
produce different data file. How to write a system to deal with such
change. The website just needs data to display. Your job is to
provide the specified data format for the website.
Here comes a solution. Use an interface type to converge the
different data file format. The following is a skeleton of
implementation.
//Let's say the interface is Displayinterface Display {
//load a filepublic void load(String fileName);
-
8/20/2019 Design Pattern QA
25/171
//parse the file and make a consistent datatype
public void formatConsistency();
}
//deal with plain text fileclass CSVFile implements Display{
public void load(String textfile) {System.out.println("load from a txt
file");}public void formatConsistency() {
System.out.println("txt file formatchanged");
}}
//deal with XML format fileclass XMLFile implements Display {
public void load(String xmlfile) {System.out.println("load from an xml
file");}public void formatConsistency() {
System.out.println("xml file formatchanged");}
}
-
8/20/2019 Design Pattern QA
26/171
//deal with binary format fileclass DBFile implements Display {
public void load(String dbfile) {System.out.println("load from a db file");
}public void formatConsistency() {
System.out.println("db file formatchanged");
}}
//Test the functionalityclass TestFactory {
public static void main(String[] args) {Display display = null;
//use a command line data as a triggerif (args[0].equals("1"))
display = new CSVFile();else if (args[0].equals("2"))
display = new XMLFile();else if (args[0].equals("3"))
display = new DBFile();else
System.exit(1);
//converging code followsdisplay.load("");display.formatConsistency();
}}//after compilation and run it
-
8/20/2019 Design Pattern QA
27/171
C:\>java TestFactory 1load from a txt filetxt file format changed
C:\>java TestFactory 2load from an xml filexml file format changed
C:\>java TestFactory 3load from a db filedb file format changed
In the future, the company may add more data file with different
format, a programmer just adds a new class in accordingly. Such
design saves a lot of code and is easy to maintain.
-
8/20/2019 Design Pattern QA
28/171
d.
Prototype
Definition
Cloning an object by reducing the cost of creation.
Where to use & benefits
When there are many subclasses that differ only in the kind of
objects, A system needs independent of how its objects are created,
composed, and represented.
Dynamic binding or loading a method.
Use one instance to finish job just by changing its state or
parameters.
Add and remove objects at runtime.
Specify new objects by changing its structure. Configure an application with classes dynamically.
Related patterns include
o Abstract Factory, which is often used together with
prototype. An abstract factory may store some prototypes
for cloning and returning objects.o Composite, which is often used with prototypes to make a
part-whole relationship.o Decorator , which is used to add additional functionality to
the prototype.
Example
-
8/20/2019 Design Pattern QA
29/171
Dynamic loading is a typical object-oriented feature and prototype
example. For example, overriding method is a kind of prototype
pattern.
interface Shape {public void draw();
}
class Line implements Shape {public void draw() {
System.out.println("line");
}}
class Square implements Shape {public void draw() {
System.out.println("square");}
}
class Circle implements Shape {public void draw() {
System.out.println("circle");}
}
-
8/20/2019 Design Pattern QA
30/171
class Painting {public static void main(String[] args) {
Shape s1 = new Line();Shape s2 = new Square();Shape s3 = new Circle();paint(s1);paint(s2);paint(s3);
}static void paint(Shape s) {
s.draw();}
}----------------------------If we want to make code more readable or do morestuff, we can code the paint method in thefollowing way:
static void paint(Shape s){if ( s instanceof Line)
s.draw();//more job here
if (s instanceof Square)s.draw();//more job here
if (s instanceof Circle)s.draw();
//more job here}nd Prompt
C:\> java Paintinglinesquarecircle
-
8/20/2019 Design Pattern QA
31/171
The paint method takes a variable of Shape type at runtime. The
draw method is called based on the runtime type.
Overloading method is a kind of prototype too.
class Painting {public void draw(Point p, Point p2) {
//draw a line}public void draw(Point p, int x, int y) {
//draw a square}
public void draw(Point p, int x) {//draw a circle
}}
The draw method is called to draw the related shape based on the
parameters it takes.
The prototype is typically used to clone an object, i.e. to make acopy of an object. When an object is complicated or time
consuming to be created , you may take prototype pattern to make
such object cloneable. Assume the Complex class is a complicated,
you need to implement Cloneable interface and override the clone
method(protected Object clone()).
class Complex implements Cloneable {int[] nums = {1,2,3,4,5};public Object clone() {
try {return super.clone();
}catch(CloneNotSupportedException cnse) {System.out.println(cnse.getMessage());return null;
}
-
8/20/2019 Design Pattern QA
32/171
}int[] getNums() {
return nums;}
}class Test {
static Complex c1 = new Complex();static Complex makeCopy() {
return (Complex)c1.clone();}public static void main(String[] args) {
Complex c1 = makeCopy();int[] mycopy = c1.getNums();for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);}
}
C:\ Command Prompt
C:\> java Test12345
Cloning is a shallow copy of the original object. If the cloned
object is changed, the original object will be changed accordingly.
See the following alteration.
class Complex implements Cloneable {int[] nums = {1,2,3,4,5};public Object clone() {
try {return super.clone();
}catch(CloneNotSupportedException cnse) {System.out.println(cnse.getMessage());
return null;
-
8/20/2019 Design Pattern QA
33/171
}}int[] getNums() {
return nums;}
}class Test {
Complex c1 = new Complex();Complex makeCopy() {
return (Complex)c1.clone();}public static void main(String[] args) {
Test tp = new Test();Complex c2 = tp.makeCopy();int[] mycopy = c2.getNums();mycopy[0] = 5; System.out.println();System.out.print("local array: ");for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);System.out.println();
System.out.print("cloned object: ");for(int ii = 0; ii < c2.nums.length; ii++)
System.out.print(c2.nums[ii]);System.out.println();
System.out.print("original object: ");for(int iii = 0; iii < tp.c1.nums.length;iii++)
System.out.print(tp.c1.nums[iii]);}
-
8/20/2019 Design Pattern QA
34/171
C:\> java Test
local array: 52345cloned object: 52345original object: 52345
To avoid such side effect, you may use a deep copy instead of a
shallow copy. The following shows the alteration to the above
example, note that the Complex class doesn't implement Cloneable
interface.
class Complex { int[] nums = {1,2,3,4,5};public Complex clone() {
return new Complex();} int[] getNums() {
return nums;
}}class Test2 {
Complex c1 = new Complex();Complex makeCopy() {
return (Complex)c1.clone();}public static void main(String[] args) {
Test2 tp = new Test2();Complex c2 = tp.makeCopy();int[] mycopy = c2.getNums();mycopy[0] = 5;
System.out.println();System.out.print("local array: ");for(int i = 0; i < mycopy.length; i++)
System.out.print(mycopy[i]);
-
8/20/2019 Design Pattern QA
35/171
System.out.println();
System.out.print("cloned object: ");for(int ii = 0; ii < c2.nums.length; ii++)
System.out.print(c2.nums[ii]);System.out.println();
System.out.print("original object: ");for(int iii = 0; iii < tp.c1.nums.length;
iii++)System.out.print(tp.c1.nums[iii]);
}}
C:\> java Test2
local array: 52345cloned object: 52345original object: 12345
e.
Singleton
Definition
One instance of a class or one value accessible globally in anapplication.
Where to use & benefits
Ensure unique instance by defining class final to prevent
cloning.
May be extensible by the subclass by defining subclass final.
-
8/20/2019 Design Pattern QA
36/171
Make a method or a variable public or/and static.
Access to the instance by the way you provided.
Well control the instantiation of a class.
Define one value shared by all instances by making it static. Related patterns include
o Abstract factory, which is often used to return unique
objects.o
Builder , which is used to construct a complex object,
whereas a singleton is used to create a globally accessible
object.
o Prototype, which is used to copy an object, or create an
object from its prototype, whereas a singleton is used to
ensure that only one prototype is guaranteed.
Example
One file system, one window manager, one printer spooler, one
Test engine, one Input/Output socket and etc.
To design a Singleton class, you may need to make the class final
like java.Math, which is not allowed to subclass, or make a variable
or method public and/or static, or make all constructors private to
prevent the compiler from creating a default one.
For example, to make a unique remote connection,
final class RemoteConnection {private Connect con;private static RemoteConnection rc = new
RemoteConnection(connection);private RemoteConnection(Connect c) {
con = c;....
}
-
8/20/2019 Design Pattern QA
37/171
public static RemoteConnectiongetRemoteConnection() {
return rc;}public void setConnection(Connect c) {
this(c);}
}
usage:RemoteConnection rconn =RemoteConnection.getRemoteConnection;rconn.loadData();...
The following statement may fail because of theprivate constructorRemoteConnection con = newRemoteConnection(connection); //failed
//failed because you cannot subclass it (finalclass)class Connection extends RemoteConnection {}
For example, to use a static variable to control the instance;
class Connection {
public static boolean haveOne = false;public Connection() throws Exception{
if (!haveOne) {doSomething();haveOne = true;
}else {throw new Exception("You cannot have a
second instance");
}
-
8/20/2019 Design Pattern QA
38/171
}public static Connection getConnection()
throws Exception{return new Connection();
}void doSomething() {}//...public static void main(String [] args) {
try {Connection con = new Connection();
//ok}catch(Exception e) {
System.out.println("first: "+e.getMessage());
}try {
Connection con2 =Connection.getConnection(); //failed.
}catch(Exception e) {System.out.println("second: "
+e.getMessage());}
}}
C:\ Command Prompt
C:\> java Connectionsecond: You cannot have a secondinstance
For example to use a public static variable to ensure a unique.
class Employee {public static final int companyID = 12345;public String address;
-
8/20/2019 Design Pattern QA
39/171
//...
}class HourlyEmployee extends Employee {
public double hourlyRate;//....
}class SalaryEmployee extends Employee {
public double salary;//...
}class Test {
public static void main(String[] args) {Employee Evens = new Employee();HourlyEmployee Hellen = new
HourlyEmployee();SalaryEmployee Sara = new SalaryEmployee();System.out.println(Evens.companyID ==
Hellen.companyID); //trueSystem.out.println(Evens.companyID ==
Sara.companyID); //true}
}
C:\ Command Prompt
C:\> java Testtruetrue
The companyID is a unique and cannot be altered by
all subclasses.
-
8/20/2019 Design Pattern QA
40/171
Note that Singletons are only guaranteed to beunique within a given class
loader. If you use the same class across multipledistinct enterprise
containers, you'll get one instance for eachcontainer.
Whether you need to use synchronized keyword tomanage the method access, it depends on yourproject situation and thread controlling.
-
8/20/2019 Design Pattern QA
41/171
Structural Patterns
a. Adapter
Definition
Convert the existing interfaces to a new interface to achieve
compatibility and reusability of the unrelated classes in one
application. Also known as Wrapper pattern.
Where to use & benefits
Try to match an interface(WindowAdapter, etc.)
Make unrelated classes work together.
Multiple compatibility.
Increase transparency of classes.
Make a pluggable kit. Delegate objects.
Highly class reusable.
Achieve the goal by inheritance or by composition
Related patterns include
o Proxy, which provides the same interface as its subject,
whereas an adapter provides a different interface to the
object it adapts.o Decorator , which focuses on adding new functions to an
object, whereas an adapter coordinates two different
objects.
o Bridge, which tries to separate an interface from its
implementation and make an object vary independently,
whereas an adapter tries to change and cooperate the
interface of an object.
-
8/20/2019 Design Pattern QA
42/171
Example
The famous adapter classes in Java API are
WindowAdapter,ComponentAdapter, ContainerAdapter,FocusAdapter, KeyAdapter, MouseAdapter and
MouseMotionAdapter.
As you know, WindowListner interface has seven methods.
Whenever your class implements such interface, you have to
implements all of the seven methods. WindowAdapter class
implements WindowListener interface and make seven empty
implementation. When you class subclass WindowAdapter class,
you may choose the method you want without restrictions. The
following give such an example.
public interface Windowlistener {public void windowClosed(WindowEvent e);public void windowOpened(WindowEvent e);
public void windowIconified(WindowEvent e);public void windowDeiconified(WindowEvent e);public void windowActivated(WindowEvent e);public void windowDeactivated(WindowEvent e);public void windowClosing(WindowEvent e);
}
-
8/20/2019 Design Pattern QA
43/171
public class WindowAdapter implementsWindowListner{
public void windowClosed(WindowEvent e){}public void windowOpened(WindowEvent e){}public void windowIconified(WindowEvent e){}public void windowDeiconified(WindowEvent e){}public void windowActivated(WindowEvent e){}public void windowDeactivated(WindowEvent e){}public void windowClosing(WindowEvent e){}
}
Here is a test program
import javax.swing.*;import java.awt.event.*;class Test extends JFrame {
public Test () {setSize(200,200);setVisible(true);
addWindowListener(new Closer());}public static void main(String[] args) {
new Test();}class Closer extends WindowAdapter {
public void windowClosing(WindowEvent e) {System.exit(0);
}}
}
To reuse classes and make new class compatible with existing ones.
For example, A clean system is already designed, you want to add
more job in, the Extra interface uses adapter pattern to plug in the
existing system.
-
8/20/2019 Design Pattern QA
44/171
interface Clean {public void makeClean();
}class Office implements Clean{
public void makeClean() {System.out.println("Clean Office");
}}class Workshop implements Clean{
public void makeClean() {System.out.println("Clean Workshop");
}}
interface Extra extends Clean{public void takeCare();
}class Facility implements Extra{
public void makeClean() {System.out.println("Clean Facility");
}public void takeCare() {
System.out.println("Care has been taken");}
}In order to reuse Workshop and Office classes,wecreate an adapter interface Extra and
add new job takeCare in the system.
class Test {static void Jobs (Extra job) {
if (job instanceof Clean)((Clean)job).makeClean();
if (job instanceof Extra)((Extra)job).takeCare();
}
-
8/20/2019 Design Pattern QA
45/171
public static void main(String[] args) {Extra e = new Facility();Jobs(e);Clean c1 = new Office();Clean c2 = new Workshop();c1.makeClean();c2.makeClean();e.makeClean();
}
} C:\ Command Prompt
C:\> java TestClean FacilityCare has been takenClean OfficeClean WorkshopClean Facility
By composition, we can achieve adapter pattern. It is also called
wrapper. For example, a Data class has already been designed andwell tested. You want to adapt such class to your system. You may
declare it as a variable and wrapper or embed it into your class.
//well-tested classclass Data {
public void add(Info){}public void delete(Info) {}
public void modify(Info){}//...
}
//Use Data class in your own classclass AdaptData {
Data data;public void add(Info i) {
data.add(i);
-
8/20/2019 Design Pattern QA
46/171
//more job}public void delete(Info i) {
data.delete(i);//more job
}public void modify(Info i) {
data.modify(i);//more job
}//more stuff here//...
}
-
8/20/2019 Design Pattern QA
47/171
b. Bridge
Definition
Decouple an abstraction or interface from its implementation so
that the two can vary independently.
Where to use & benefits
Want to separate abstraction and implementation permanently
Share an implementation among multiple objects
Want to improve extensibility
Hide implementation details from clients
Related patterns include
o Abstract Factory, which can be used to create and
configure a particular bridge.o Adapter , which makes unrelated classes work together,
whereas a bridge makes a clear-cut between abstraction
and implementation.
Examples
If you have a question database, you may want to develop a
program to display it based on the user selection. The following is asimple example to show how to use a Bridge pattern to decouple
the relationship among the objects.
import java.util.*;
//abstractioninterface Question {
-
8/20/2019 Design Pattern QA
48/171
public void nextQuestion();public void priorQuestion();public void newQuestion(String q);public void deleteQuestion(String q);public void displayQuestion();public void displayAllQuestions();
}
//implementationclass QuestionManager {
protected Question questDB; //instantiate itlaterpublic String catalog;
public QuestionManager(String catalog) {this.catalog = catalog;
}
public void next() {questDB.nextQuestion();
}
-
8/20/2019 Design Pattern QA
49/171
public void prior() {questDB.priorQuestion();
}
public void newOne(String quest) {questDB.newQuestion(quest);
}
public void delete(String quest) {questDB.deleteQuestion(quest);
}
public void display() {questDB.displayQuestion();
}
public void displayAll() {System.out.println("Question Catalog: " +
catalog);questDB.displayAllQuestions();
}}
//further implementationclass QuestionFormat extends QuestionManager {
public QuestionFormat(String catalog){super(catalog);}
public void displayAll() {
System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~");
super.displayAll();
-
8/20/2019 Design Pattern QA
50/171
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~");
}}
//decoupled implementationclass JavaQuestions implements Question {
private List questions = newArrayList();
private int current = 0;
public JavaQuestions() {//load from a database and fill in the
containerquestions.add("What is Java? ");questions.add("What is an interface? ");questions.add("What is cross-platform? ");questions.add("What is UFT-8? ");questions.add("What is abstract? ");questions.add("What is Thread? ");questions.add("What is multi-threading?
");
}
public void nextQuestion() {
if( current 0 )
current--;
}
-
8/20/2019 Design Pattern QA
51/171
public void newQuestion(String quest) {
questions.add(quest);}
public void deleteQuestion(String quest) {questions.remove(quest);
}
public void displayQuestion() {System.out.println( questions.get(current)
);}
public void displayAllQuestions() {for (String quest : questions) {
System.out.println(quest);}
}}
class TestBridge {public static void main(String[] args) {
QuestionFormat questions = newQuestionFormat("Java Language");
questions.questDB = newJavaQuestions();//can be hooked up with otherquestion class
//questions.questDB = newCsharpQuestions();
//questions.questDB = newCplusplusQuestions();
questions.display();
-
8/20/2019 Design Pattern QA
52/171
questions.next();
questions.newOne("What is object? ");questions.newOne("What is reference
type?");
questions.displayAll();}
}//need jdk1.5 to compile
C:\ Command Prom
C:\> javac TestBridge.javaC:\> java TestBridgeWhat is Java?
~~~~~~~~~~~~~~~~~~~~~~~~Question Catalog: Java LanguageWhat is Java?What is an interface?What is cross-platform?What is UFT-8?What is abstract?What is Thread?What is multi-threading?What is object?What is reference type?~~~~~~~~~~~~~~~~~~~~~~~~
C:\>
Note that the JavaQuestion class can be launched independently
and work as its own system. Here we just show you how to use
Bridge pattern to decouple the interface from its implementation.
-
8/20/2019 Design Pattern QA
53/171
c.
Composite
Definition
Build a complex object out of elemental objects and itself like a
tree structure.
Where to use & benefits Want to represent a part-whole relationship like tree folder
system
Group components to form larger components, which in turn
can be grouped to form still larger components.
Related patterns include
o Decorator , which is often used with composite pattern and
with the same parent class.
o Flyweight, which is used with composite pattern to share
components.o Iterator , which is used to traverse the composites.
o Visitor , which localizes operations across composite and
leaf classes.
Example
A component has many elements and itself which has many
elements and itself, etc. A file system is a typical example.
Directory is a composite pattern. When you deal with Directory
object, if isFile() returns true, work on file, if isDirectory() returns
true, work on Directory object.
-
8/20/2019 Design Pattern QA
54/171
class Directory {Directory dir;File[] f;...
boolean isDirectory() {return f == null;
}boolean isFile() {
return f != null;}File getFile(int i) {
if (isFile())return f[i];
return null'}Directory getDirectory() {
if (isDirectory())return dir;
return null;}....
}
For example, General Manager may have several employees and
some of employees are Managers which have several employees.
To illustrate such issue, we design a simple Manager class.
class Employee {String name;double salary;Employee(String n, double s){
name = n;salary = s;
}String getName() {
return name;
-
8/20/2019 Design Pattern QA
55/171
}double getSalary() {
return salary;}public String toString() {
return "Employee " + name;}
}class Manager {
Manager mgr;Employee[] ely;String dept;Manager(Manager mgr,Employee[] e, String d ) {
this(e, d);this.mgr = mgr;
}
Manager(Employee[] e, String d) {ely = e;dept =d;
}String getDept() {
return dept;}
-
8/20/2019 Design Pattern QA
56/171
Manager getManager() {return mgr;
}Employee[] getEmployee() {
return ely;}public String toString() {
return dept + " manager";}
}
class Test {public static void main(String[] args) {
Employee[] e1 = {new Employee("Aaron", 50),new Employee("Betty",
60)};Manager m1 = new Manager(e1, "Accounting");
Employee[] e2 = {new Employee("Cathy", 70),new Employee("Dan", 80),new Employee("Eliz", 90)};
Manager m2 = new Manager(m1, e2,"Production");
System.out.println(m2);Employee[] emp = m2.getEmployee();if (emp != null)
for (int k = 0; k < emp.length; k++)System.out.println(" "+emp[k]+"Salary: $"+ emp[k].getSalary());
Manager m = m2.getManager();System.out.println(" " + m);if (m!= null) {
Employee[] emps = m.getEmployee();if (emps != null)
for (int k = 0; k < emps.length; k++)
-
8/20/2019 Design Pattern QA
57/171
System.out.println(" " +emps[k]+" Salary: $"+ emps[k].getSalary());
}}
}
C:\ Command Prompt
C:\> java TestProduction manager
Employee Cathy Salary: $70.0Employee Dan Salary: $80.0Employee Eliz Salary: $90.0Accounting managerEmployee Aaron Salary: $50.0Employee Betty Salary: $60.0
-
8/20/2019 Design Pattern QA
58/171
d.
Decorator
Definition
Attach additional responsibilities or functions to an object
dynamically or statically. Also known as Wrapper.
Where to use & benefits
Provide an alternative to subclassing. Add new function to an object without affecting other objects.
Make a responsibility easily added and removed dynamically.
More flexibility than static inheritance.
Transparent to the object.
Related patterns include
o Adapter pattern, which provides a different interface to
the object it adapts, whereas a decorator changes anobject's responsibilities,
o Proxy pattern, which controls access to the object,
whereas a decorator focuses on adding new functions to
an object,
o Composite pattern, which aggregates an object, whereas a
decorator adds additional responsibilities to an object, and
o Strategy pattern, which changes the guts of an object,
whereas a decorator changes the skin of an object.
o Facade pattern, which provides a way of hiding a complex
class, whereas a decorator adds function by wrapping a
class.
Example
-
8/20/2019 Design Pattern QA
59/171
A JScrollPane object can be used to decorate a JTextArea object or
a JEditorPane object. A window can be decorated with different
borders like BevelBorder, CompoundBorder, EtchedBorder
TitledBorder etc. These border classes working as decorators are provided in Java API.
Decorator pattern can be used in a non-visual fashion. For example,
BufferedInputStream, DataInputStream, and CheckedInputStream
are decorating objects of FilterInputStream class. These decorators
are standard Java API classes.
To illustrate a simple decorator pattern in non-visual manner, wedesign a class that prints a number. We create a decorator class that
adds a text to the Number object to indicate that such number is a
random number. Of course we can subclass the Number class to
achieve the same goal. But the decorator pattern provides us an
alternative way.
import java.util.Random;class Number {public void print() {
System.out.println(new Random().nextInt());}
}
class Decorator {
public Decorator() {System.out.print("Random number: ");//add
a description to the number printednew Number().print();
}}
class SubNumber extends Number{
public SubNumber() {
-
8/20/2019 Design Pattern QA
60/171
super();System.out.print("Random number: ");print();
}}
class Test {public static void main(String[] args) {
new Decorator();new SubNumber();
}}java TestRandom number: 145265744Random number: 145265755
e.
Façade
Definition
Make a complex system simpler by providing a unified or general
interface, which is a higher layer to these subsystems.
Where to use & benefits
Want to reduce complexities of a system.
Decouple subsystems , reduce its dependency, and improve
portability.
Make an entry point to your subsystems.
-
8/20/2019 Design Pattern QA
61/171
Minimize the communication and dependency between
subsystems.
Security and performance consideration.
Shield clients from subsystem components. Simplify generosity to specification.
Related patterns include
o Abstract Factory, which is often used to create an
interface for a subsystem in an independent way, and can
be used as an alternative way to a facade.o Singleton, which is often used with a facade.
o Mediator , which is similar to facade, but a facade doesn't
define new functionality to the subsystem.
Example
JDBC design is a good example of Façade pattern. A database
design is complicated. JDBC is used to connect the database and
manipulate data without exposing details to the clients.
Security of a system may be designed with Façade pattern. Clients'
authorization to access information may be classified. General
users may be allowed to access general information; special guests
may be allowed to access more information; administrators and
executives may be allowed to access the most important
information. These subsystems may be generalized by one
interface. The identified users may be directed to the relatedsubsystems.
interface General {public void accessGeneral();
}interface Special extends General {
public void accessSpecial();
}
-
8/20/2019 Design Pattern QA
62/171
interface Private extends General {public void accessPrivate();
}
class GeneralInfo implements General {public void accessGeneral() {//...}//...
}class SpecialInfo implements Special{
public void accessSpecial() {//...
}public void accessGeneral() {}//...
}class PrivateInfo implements Private, Special {
public void accessPrivate() {// ...}public void accessSpecial() {//...}public void accessGeneral() {// ...}
//...}
class Connection {//...
if (user is unauthorized) throw newException();
if (user is general) return new GeneralInfo();
-
8/20/2019 Design Pattern QA
63/171
if (user is special) return new SpecialInfo();if (user is executive) return new
PrivateInfo();//...
}
The above code example illustrates that the whole system is not
exposed to the clients. It depends on the user classification.
Mr. SudHakar Chavali proposes a better design, similar to the
above, but avoids repeated code. Look at code below.interface General {
public void accessGeneral();}
interface Special extends General {
public void accessSpecial();
}
interface Private extends General {
public void accessPrivate();
}
class GeneralInfo implements General {
public void accessGeneral() {
//...}
//...
}
-
8/20/2019 Design Pattern QA
64/171
class SpecialInfo extends GeneralInfo implementsSpecial{
public void accessSpecial() {
//...}
}
class PrivateInfo extends SpecialInfo implementsPrivate {
public void accessPrivate() {
// ...
}
//...}
To avoid repeated code, SpecialInfo become subclass of
GeneralInfo and PrivateInfo becomes subclass of SpecialInfo.
When a person is exposed to special information, that person is
allowed to access general information also. When a person is
exposed to private information, that person is allowed to accessgeneral information and special information also.
When you design a mortgage process system, you may consider the
process of checking client's bank, credit and other loan information.
Facade design may be a choice.
-
8/20/2019 Design Pattern QA
65/171
f.
Flyweight
Definition
Make instances of classes on the fly to improve performance
efficiently, like individual characters or icons on the screen.
Where to use & benefits
Need to instantiate a large amount of small and fine-grained
classes.
Need icons to represent object.
An object extrinsic state can be shared by classes.
Reduce the number of objects created, decrease memory
footprint and increase performance.
Increase runtime cost associated with transferring, finding, or
computing extrinsic data. Related patterns include
o Composite, which supports recursive structures, whereas
an flyweight is often applied on it.
o Factory Method, which produces specific object upon
requirement, whereas an flyweight uses it to reduce
objects.
o State, which allows an object to alter its behavior when its
internal state is changed, whereas a flyweight is best
implemented on it.
o Strategy, which allows an algorithm vary independently to
suit its needs, whereas a flyweight is based on such
strategy.
Examples
-
8/20/2019 Design Pattern QA
66/171
In order to share an object, we may declare an interface and an
intrinsic state through which flyweights can receive and act on it. If
you want to show a file system with folders to show the directories
or subdirectories, you don't need to load all the files or directoriesat one loading time. You may show the upper level folders first. If
the user clicks a folder, then load its subdirectories and files. The
shared trigger is mouse-clicked. The composite pattern may be
combined to define the flyweight system.
class Folder {void draw(..) {}
}class FolderFactory {
...if (selected) {
return aFolder;else
return aFile;...
}
...
To show how to use flyweight to reduce object creation, we will
make a program to draw 1000 circles with 6 different colors.
Before we customize it to a flyweight design, it is coded as follows:
-
8/20/2019 Design Pattern QA
67/171
import java.awt.*;import java.awt.Color;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;
class Test extends JFrame{private static final Color colors[] = {
Color.red, Color.blue,
Color.yellow, Color.orange,
Color.black, Color.white };private static final int WIDTH_ = 400,
HEIGHT = 400,NUMBER_OF_CIRCLES =
1000;
public Test() {Container contentPane = getContentPane();
JButton button = new JButton("Draw Circle");final JPanel panel = new JPanel();
contentPane.add(panel,BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);
setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setVisible(true);
button.addActionListener(newActionListener() {
public void actionPerformed(ActionEvent
event) {
-
8/20/2019 Design Pattern QA
68/171
Graphics g = panel.getGraphics();
for(int i=0; i < NUMBER_OF_CIRCLES;++i) {
g.setColor(getRandomColor());int r = getRandomR();g.drawOval(getRandomX(),
getRandomY(), r, r); }
}});
}
private int getRandomX() {return (int)(Math.random()*WIDTH );
}private int getRandomY() {
return (int)(Math.random()*HEIGHT);}private int getRandomR() {
return (int)(Math.random()*(HEIGHT/10));}private Color getRandomColor() {
returncolors[(int)(Math.random()*colors.length)];
}public static void main(String[] args) {
Test test = new Test();}}
Copy, paste above code, and run it to see the functionality. and
Prompt
C:\> java Test
-
8/20/2019 Design Pattern QA
69/171
Note that the above program doesn't take advantage of reusability
of OOP. We will customize it and make a Circle object, so the
Circle object can be reused.
class Circle {private Color color;
public Circle(Color color) {this.color = color;
}public void draw(Graphics g, int x, int y, int
r) { g.setColor(color);g.drawOval(x, y, r, r);
}}
Then we rewrite the program. It is possible for people to rewrite
with Circle object in the following way:
import java.awt.*;import java.awt.Color;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;
class Test extends JFrame{private static final Color colors[] = {
Color.red, Color.blue,
Color.yellow, Color.orange,
Color.black, Color.white };private static final int WIDTH = 400,
HEIGHT = 400,NUMBER_OF_CIRCLES =
1000;
-
8/20/2019 Design Pattern QA
70/171
public Test() {
Container contentPane = getContentPane();
JButton button = new JButton("Draw Circle");final JPanel panel = new JPanel();
contentPane.add(panel,BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);setSize(WIDTH ,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setVisible(true);
button.addActionListener(newActionListener() {
public void actionPerformed(ActionEventevent) {
Graphics g = panel.getGraphics();
for(int i=0; i < NUMBER_OF_CIRCLES; ++i){
Circle circle = newCircle(getRandomColor());
circle.draw(g, getRandomX(), getRandomY(),getRandomR());//1000 object created.
}}
});}
private int getRandomX() {return (int)(Math.random()*WIDTH );
}
private int getRandomY() {return (int)(Math.random()*HEIGHT);
-
8/20/2019 Design Pattern QA
71/171
}private int getRandomR() {
return (int)(Math.random()*(HEIGHT/10));}private Color getRandomColor() {
returncolors[(int)(Math.random()*colors.length)];
}public static void main(String[] args) {
Test test = new Test();}
}
From the above code, you may note that 1000 circle object has
been created. It is memory consuming.
To improve it, we will create a CircleFactory class to customize it
by using flyweight design pattern. Since we just draw circle with
different colors, we can store color info in a hashmap. If a circle
has been drawn, the new circle will be checked with color. If thecircle with the same color has been found in the hashmap, the circle
will share the instance which is picked up from the hashmap
instead of creating a new one. We will reuse the object with
different state, that is to say we will share the instance and draw the
circle with different start position and radius on the fly.
class CircleFactory {
//store colorprivate static final HashMap circleByColor =
new HashMap();
public static Circle getCircle(Color color) {Circle circle =
(Circle)circleByColor.get(color);
if(circle == null) {
-
8/20/2019 Design Pattern QA
72/171
circle = new Circle(color);circleByColor.put(color, circle);System.out.println("Creating " + color +
" circle");//see how many objects we create oncommand line
}return circle;
}}
So our test program will be coded as follows:
import java.awt.*;import java.util.HashMap;import java.awt.Color;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;
class Test extends JFrame{
private static final Color colors[] = {Color.red, Color.blue,
Color.yellow, Color.orange,
Color.black, Color.white };private static final int WIDTH = 400,
HEIGHT = 400,
NUMBER_OF_CIRCLES =1000;
public Test() {Container contentPane = getContentPane();
JButton button = new JButton("Draw Circle");final JPanel panel = new JPanel();
-
8/20/2019 Design Pattern QA
73/171
contentPane.add(panel,BorderLayout.CENTER);
contentPane.add(button, BorderLayout.SOUTH);setSize(WIDTH,HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setVisible(true);
button.addActionListener(newActionListener() {
public void actionPerformed(ActionEventevent) {
Graphics g = panel.getGraphics();for(int i=0; i < NUMBER_OF_CIRCLES;
++i) {Circle circle =
CircleFactory.getCircle(getRandomColor());circle.draw(g, getRandomX(),
getRandomY(),getRandomR()); //Since we have 6 different colors,
we have 6 objects created.}
}});
}public static void main(String[] args) {
Test test = new Test();
}private int getRandomX() {return (int)(Math.random()*WIDTH );
}private int getRandomY() {
return (int)(Math.random()*HEIGHT);}private int getRandomR() {
return (int)(Math.random()*(HEIGHT/10));
-
8/20/2019 Design Pattern QA
74/171
}private Color getRandomColor() {
returncolors[(int)(Math.random()*colors.length)];
}}
class CircleFactory {private static final HashMap circleByColor =
new HashMap();
public static Circle getCircle(Color color) {Circle circle =
(Circle)circleByColor.get(color);
if(circle == null) {circle = new Circle(color);circleByColor.put(color, circle);System.out.println("Creating " + color +
" circle");}return circle;
}}
class Circle {private Color color;
public Circle(Color color) {this.color = color;
}public void draw(Graphics g, int x, int y, int
r) {g.setColor(color);g.drawOval(x, y, r, r);
}
-
8/20/2019 Design Pattern QA
75/171
}
Copy, paste above code and run it. You will see the printout from
the command line, that you only have 6 objects created, not 1000
objects because you only have 6 colors. Such a big reduction of
object creation will improve your program performance
dramatically.
C:\ Command Prompt
C:\> java TestCreatingjava.awt.Color[r=255,g=0,b=0]circleCreatingjava.awt.Color[r=0,g=0,b=0] circleCreatingjava.awt.Color[r=255,g=200,b=0]
circleCreatingjava.awt.Color[r=255,g=255,b=0]circleCreatingjava.awt.Color[r=0,g=0,b=255]circleCreating
java.awt.Color[r=255,g=255,b=255]circle
Flyweight design is effective with instantiating a large amount of
small and fine-grained classes by combining with factory design
pattern.
-
8/20/2019 Design Pattern QA
76/171
If you have jdk1.5 installed, you may need to use a tool to check if
you save the memory by running your commands as follows:
C:\ Command Prompt
C:\> java -Dcom.sun.management.jmxremote Test
And open another console as follows:
C:\ Command Prompt
C:\> jconsole
The jconsole tool will hook up your program Test to give your
statistic numbers about your program, such as threads, heap,
memory, VM, etc.
String class is designed with Flyweight design pattern. It has
similar structure as above example. When you create a string
constant, such constant is stored in a pool. When the second string
is created, it will be checked to see if it has been created. If it is
true, the second string instance will be picked up from the string
pool instead of creating a new one. This is why the following code
makes sense, but bothers many people.String s1 = "hello";String s2 = "hello"; //store in a string pool.String s3 = new String("hello");
System.out.println(s1==s2); //true, share the samememmory addressSystem.out.println(s1==s3); //false
-
8/20/2019 Design Pattern QA
77/171
g.
Proxy
Definition
Use a simple object to represent a complex one or provide a
placeholder for another object to control access to it.
Where to use & benefits
If creating an object is too expensive in time or memory. Postpone the creation until you need the actual object.
Load a large image (time consuming).
Load a remote object over network during peak periods.
Access right is required to a complex system.
Related patterns include
o Adapter pattern, which provides a different interface to
the object it adapts, whereas a proxy provides the sameinterface as its subject, and
o Decorator pattern, which focuses on adding new functions
to an object, whereas a proxy controls access to the object.
Example
When loading a large image, you may create some light object to
represent it until the image is loaded completely. Usually a proxy
object has the same methods as the object it represents. Once the
object is loaded, it passes on the actual object. For example,
abstract class Graphic {public abstract void load();public abstract void draw();
...
-
8/20/2019 Design Pattern QA
78/171
}class Image extends Graphic{
public void load() {...
}public void draw() {...}...
}class ImgProxy extends Graphic {
public void load() {if(image == null) {
image = new Image(filename);}...
public void draw() {...
}...
}
Behavioral Patterns
a.
Chain of Responsibility
Definition
Let more than one object handle a request without their knowing
each other. Pass the request to chained objects until it has been
handled.
-
8/20/2019 Design Pattern QA
79/171
Where to use & benefits
One request should be handled by more than one object.
Don't know which object should handle a request, probably
more than one object will handle it automatically.
Reduce coupling.
Flexible in handling a request.
Related patterns include
o Composite, which a chain of responsibility pattern is often
applied in conjunction with.
Example
The Java Servlet filter framework is an example of chain of
resposibility design. Note that the chain.doFilter() is the method
that should be called to make the chain roll. If the subclass missed
it, the whole chain would be stopped or blocked.
Java exception handling is another example of chain ofresponsibility design. When an error occurs, the exception call will
look for a handling class. If there is no handler, the super Exception
class will be called to throw the exception. Otherwise, the handler
class will handle it.
Here comes a simple example, just to show how chain of
responsibility works. Whenever you spend company's money, you
need get approval from your boss, or your boss's boss. Let's say, the
leadership chain is:
Manager-->Director-->Vice President-->President
-
8/20/2019 Design Pattern QA
80/171
The following is a command line program to check who is
responsible to approve your expenditure.
import java.io.*;abstract class PurchasePower {
protected final double base = 500;protected PurchasePower successor;
-
8/20/2019 Design Pattern QA
81/171
public void setSuccessor(PurchasePower successor){this.successor = successor;
}
abstract public voidprocessRequest(PurchaseRequest request);}
class ManagerPPower extends PurchasePower {private final double ALLOWABLE = 10 * base;
public void processRequest(PurchaseRequestrequest ) {
if( request.getAmount() < ALLOWABLE )System.out.println("Manager will
approve $"+ request.getAmount());else
if( successor != null)successor.processRequest(request);
}}
class DirectorPPower extends PurchasePower {private final double ALLOWABLE = 20 * base;
public void processRequest(PurchaseRequestrequest ) {
if( request.getAmount() < ALLOWABLE )System.out.println("Director willapprove $"+ request.getAmount());
elseif( successor != null)
successor.processRequest(request);}
}
-
8/20/2019 Design Pattern QA
82/171
class VicePresidentPPower extends PurchasePower {private final double ALLOWABLE = 40 * base;
public void processRequest(PurchaseRequestrequest) {
if( request.getAmount() < ALLOWABLE )System.out.println("Vice President
will approve $" + request.getAmount());elseif( successor != null )
successor.processRequest(request);}
}
class PresidentPPower extends PurchasePower {private final double ALLOWABLE = 60 * base;
public void processRequest(PurchaseRequestrequest){
if( request.getAmount() < ALLOWABLE )System.out.println("President will
approve $" + request.getAmount());else
System.out.println( "Your request for$" + request.getAmount() + " needs a boardmeeting!");
}
}
class PurchaseRequest {
private int number;private double amount;private String purpose;
-
8/20/2019 Design Pattern QA
83/171
public PurchaseRequest(int number, doubleamount, String purpose){
this.number = number;this.amount = amount;this.purpose = purpose;
}
public double getAmount() {return amount;
}public void setAmount(double amt){
amount = amt;}
public String getPurpose() {return purpose;
}public void setPurpose(String reason) {
purpose = reason;}
public int getNumber(){return number;
}public void setNumber(int num) {
number = num;}
}
class CheckAuthority {public static void main(String[] args){
ManagerPPower manager = newManagerPPower();
DirectorPPower director = newDirectorPPower();
-
8/20/2019 Design Pattern QA
84/171
VicePresidentPPower vp = newVicePresidentPPower();
PresidentPPower president = newPresidentPPower();
manager.setSuccessor(director);director.setSuccessor(vp);vp.setSuccessor(president);
//enter ctrl+c to kill.try{
while (true) {System.out.println("Enter the
amount to check who should approve yourexpenditure.");
System.out.print(">");double d = Double.parseDouble(new
BufferedReader(newInputStreamReader(System.in)).readLine());
manager.processRequest(newPurchaseRequest(0, d, "General"));
}}catch(Exception e){
System.exit(1);}
}}
C:\ Command Prompt
-
8/20/2019 Design Pattern QA
85/171
C:\> javac CheckAuthority.javaC:\> java CheckAuthority
Enter the amount to check whoshould approve your expenditure.>500Manager will approve $500.0Enter the amount to check whoshould approve your expenditure.>5000
Director will approve $5000.0Enter the amount to check whoshould approve your expenditure.>11000Vice President will approve$11000.0Enter the amount to check whoshould approve your expenditure.
>30000Your request for $30000.0 needs aboard meeting!Enter the amount to check whoshould approve your expenditure.>20000President will approve $20000.0Enter the amount to check who
should approve your expenditure.>C:\>
You may redo it using interface instead of abstract class.
The composite pattern is often used with chain of responsibility.
That means a class may contain the related class that may handle
the request.
-
8/20/2019 Design Pattern QA
86/171
b. Command
Definition
Streamlize objects by providing an interface to encapsulate a
request and make the interface implemented by subclasses in order
to parameterize the clients.
Where to use & benefits
One action can be represented in many ways, like drop-down
menu, buttons and popup menu.
Need a callback function, i.e., register it somewhere to be
called later.
Specify and execute the request at different time Need to undo an action by storing its states for later retrieving.
Decouple the object with its trigger
Easily to be extensible by not touching the old structure.
Related patterns include
o Composite, which aggregates an object. You may
combine it into a composite command pattern. In general,
a composite command is an instance of the composite.o Memento, which keeps state of an object. Command
supports undo and redo.
Example
The simple example of Command pattern is to design a Command
interface and with an execute method like this:
-
8/20/2019 Design Pattern QA
87/171
public interface Command {public void execute();
}
Then, design multiple implementation classes and see how powerful the execute() method has been called dynamically.
In order to take advantage of Java built-in interfaces, we will design
a window with a drop down menu, button commands and popup
menu with command pattern.
As we know, JButton, JMenuItem and JPopupMenu have
constructors accept Action type variable. Action interface extends
ActionListener, which has the following hierarchy.
public interface EventLister {...
}
public interface ActionListener extendsEventListener {
...}
public interface Action extends ActionListener {...
}
There is an abstract class called AbstractAction which implementsAction interface. It has the following design.
public abstract class AbstractAction extendsObject
implements Action, Cloneable,Serializable
-
8/20/2019 Design Pattern QA
88/171
We will create several command classes to subclass the
AbstractAction class and pass them to the constructors of JButton,
JMenuItem and JPopupMenu classes. There is a request method
called actionPerformed(), every command classes must implementit in order to make it work. To show the concept, we just design
two actions: submit and exit. You may expand such design to your
need in your future project.
Such action can be attached to any component, AWT or Swing.
The caption, and Icon have been designed as well as tooltips.
class ExitAction extends AbstractAction {private Component target;public ExitAction(String name, Icon icon,
Component t){putValue(Action.NAME, name);putValue(Action.SMALL_ICON, icon);putValue(Action.SHORT_DESCRIPTION, name + "
the program");
target = t;} public void actionPerformed(ActionEvent evt) {
int answer =JOptionPane.showConfirmDialog(target, "Are yousure you want to exit? ", "Confirmation",
JOptionPane.YES_NO_OPTION);
if ( answer == JOptionPane.YES_OPTION) {System.exit(0);
}}
}
Similar to the above exit action, the submit action is as follows:
class SubmitAction extends AbstractAction {
-
8/20/2019 Design Pattern QA
89/171
private Component target;public SubmitAction(String name, Icon icon,
Component t){putValue(Action.NAME, name);putValue(Action.SMALL_ICON, icon);putValue(Action.SHORT_DESCRIPTION, name + "
the program");target = t;
} public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(target,"submit action clicked ");
}}
You can modify the program to add more commands in. These
command classes are decoupled from any program. It is very good
for maintenance.
The whole workable program is as follows. You can run it to see
the powerful command design pattern.
import javax.swing.*;import java.awt.event.*;import java.awt.*;
class ExitAction extends AbstractAction {private Component target;public ExitAction(String name, Icon icon,
Component t){putValue(Action.NAME, name);putValue(Action.SMALL_ICON, icon);putValue(Action.SHORT_DESCRIPTION, name + "
the program");target = t;
}
-
8/20/2019 Design Pattern QA
90/171
public void actionPerformed(ActionEvent evt) {int answer =
JOptionPane.showConfirmDialog(target, "Are yousure you want to exit? ", "Confirmation",
JOptionPane.YES_NO_OPTION);if ( answer == JOptionPane.YES_OPTION) {
System.exit(0);}
}}
-
8/20/2019 Design Pattern QA
91/171
class SubmitAction extends AbstractAction {
private Component target;public SubmitAction(String name, Icon icon,
Component t){putValue(Action.NAME, name);putValue(Action.SMALL_ICON, icon);putValue(Action.SHORT_DESCRIPTION, name + "
the program");target = t;
}public void actionPerformed(ActionEvent evt) {
JOptionPane.showMessageDialog(target,"submit action clicked ");
}}
class Test extends JFrame{Test() {
Action ea = new ExitAction("Exit", null,
this);
Action sa = new SubmitAction("Submit",
null, this);
JMenuBar jbr = new JMenuBar();JMenu dropmenu= new JMenu("File");JMenuItem submitmenu = new JMenuItem(sa);
JMenuItem exitmenu = new JMenuItem(ea);dropmenu.add(submitmenu);
dropmenu.add(exitmenu);jbr.add(dropmenu);setJMenuBar(jbr);
final JPopupMenu pop = newJPopupMenu("PopMenu");
pop.add(sa);
-
8/20/2019 Design Pattern QA
92/171
pop.add(ea);addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e){
showPopup(e);}
public void mouseReleased(MouseEvent e){
showPopup(e);}
private void showPopup(MouseEvent e) {if (e.isPopupTrigger()) {
pop.show(e.getComponent(),e.getX(),
e.getY());}
}
});JPanel jp = new JPanel();JButton subbtn = new JButton(sa);JButton exitbtn = new JButton(ea);jp.add(subbtn);jp.add(exitbtn);
Container con = getContentPane();con.add(jp, "South");
setTitle("Command pattern example");setSize(400,200);setVisible(true);
}
public static void main(String[] args) {
-
8/20/2019 Design Pattern QA
93/171
new Test();}
}java Test
A windows pops up.
Pay attention to the action buttons. The instances can be
parameterized to JButton, JMenuItem and JPopupMenu
constructors. The powerful action design (Java built-in Action
interface) makes objects like ExitAction, SubmitAction be used
everywhere. Design once, use everywhere.
c.
Interpreter
DefinitionProvides a definition of a macro language or syntax and parsing
into objects in a program.
Where to use & benefits
Need your own parser generator.
Translate a specific expression. Handle a tree-related information.
Related patterns include
o Composite, which is an instance in an interpreter.
o Flyweight, which shows how to share symbols with
abstract context.
o Iterator , which is used to traverse the tree structure.
-
8/20/2019 Design Pattern QA
94/171
o Visitor , which is used to maintain behavior of each note in
tree structure.
ExampleGiven any string expression and a token, filter out the information
you want. The below is a simple parser program. the myParser
method can be used to parse any expression. The composite, visit
and iterator patterns have been used.
import java.util.*;
class Parser{private String expression;private String token;private List result;private String interpreted;
public Parser(String e, String t) {expression = e;
token = t;}
-
8/20/2019 Design Pattern QA
95/171
public void myParser() {StringTokenizer holder = new
StringTokenizer(expression, token);String[] toBeMatched = new
String[holder.countTokens()];int idx = 0;while(holder.hasMoreTokens()) {
String item = holder.nextToken();int start = item.indexOf(",");if(start==0) {
item = item.substring(2);}
toBeMatched[idx] = item;idx ++;}result = Arrays.asList(toBeMatched);
}public List getParseResult() {
return result;}public void interpret() {
StringBuffer buffer = new StringBuffer();ListIterator list =
result.listIterator();while (list.hasNext()){
String token = (String)list.next();if (token.equals("SFO")){
token = "San Francisco";}else if(token.equals("CA")) {token = "Canada";
}//...buffer.append(" " + token);
}interpreted = buffer.toString();
}
-
8/20/2019 Design Pattern QA
96/171
public String getInterpretedResult() {return interpreted;
}public static void main(String[] args) {
String source ="dest='SFO',origin='CA',day='MON'";
String delimiter = "=,'";Parser parser = new Parser(source,
delimiter);parser.myParser();parser.interpret();String result =
parser.getInterpretedResult();System.out.println(result);
}}java Parserdest San Francisco origin Canada day MON
-
8/20/2019 Design Pattern QA
97/171
d.
Iterator
DefinitionProvide a way to move through a list of collection or aggregated
objects without knowing its internal representations.
Where to use & benefits
Use a standard interface to represent data objects.
Use s standard iterator built in each standard collection, likeList, Sort, or Map.
Need to distinguish variations in the traversal of an aggregate.
Similar to Enumeration class, but more effective.
Need to filter out some info from an aggregated collection.
Related patterns include
o Composite, which supports recursive structures, whereas
an iterator is often applied on it.o Factory Method, which provides appropriate instances
needed by an iterator subclasses.
o Memento, which is often used with an Iterator. The
iterator stores the memento internally.
Example
Employee is an interface, Manager, PieceWorker, HourlyWorker
and CommissionWorker are implementation classes of interface
Employee. EmployeeTest class will create a list and use a built-in
iterator of ArrayList class to traverse the members of the list.
import java.util.*;interface Employee {
public abstract double earnings();
-
8/20/2019 Design Pattern QA
98/171
}class Manager implements Employee {
private double weeklySalary;private String name;public Manager(String name, double s) {
this.name = name;setWeeklySalary(s);
}
void setWeeklySalary(double s) {if (s > 0) {weeklySalary = s;
} elseweeklySalary = 0;
}public double earnings() {
return weeklySalary;}public String getName() {
return name;}public String toString() {
return "Manager: " + getName();}
}
class PieceWorker implements Employee {
private double wagePerPiece;private int quantity;private String name;public PieceWorker(String name, double w, int
q) {this.name = name;setWagePerPiece(w);setQuantity(q);
}
-
8/20/2019 Design Pattern QA
99/171
void setWagePerPiece(double w) {
if (w > 0)wagePerPiece = w;
elsewagePerPiece = 0;
}
void setQuantity(int q) {if ( q > 0)
quantity = q;else
quantity = 0;}public String getName() {
return name;}public double earnings() {
return quantity * wagePerPiece;}
public String toString() {return "Piece worker: " + getName();
}}
class HourlyWorker implements Employee {
private double hourlyWage;private double hours;private String name;public HourlyWorker(String name, double w,
double h) {this.name = name;setHourlyWage(w);setHours(h);
}
-
8/20/2019 Design Pattern QA
100/171
void setHourlyWage(double w) {
if (w > 0)hourlyWage = w;
elsehourlyWage = 0;
}
void setHours(double h) {if ( 0
-
8/20/2019 Design Pattern QA
101/171
setTotalSales(totalSales);}void setSalary(double s) {
if( s > 0)salary = s;
elsesalary = 0;
}void setCommission(double c) {
if ( c > 0)commission = c;
elsecommission = 0;
}void setTotalSales(double ts) {
if (ts > 0 )totalSales = ts;
elsetotalSales = 0;
}public String getName() {
return name;}public double earnings() {
return salary + commission/100*totalSales;}public String toString() {
return "Commission worker:"+ getName();}
}
class EmployeeTest {public static void main(String[] args) {
java.util.List list = new ArrayList();
list.add(new Manager("Bill", 800.00));
-
8/20/2019 Design Pattern QA
102/171
list.add(new CommissionWorker("Newt",400.0, 3.75, 159.99));
list.add(new PieceWorker("Al", 2.5, 200));list.add(new HourlyWorker("Babara", 13.75,
40));list.add(new Manager("Peter", 1200.00));list.add(new CommissionWorker("Margret",
600.0,5.5, 200.25));list.add(new PieceWorker("Mark", 4.5,
333));list.add(new HourlyWorker("William",
31.25, 50));
System.out.println("Use built-initerator:");
Iterator iterator = list.iterator();while(iterator.hasNext()) {
Employee em =(Employee)iterator.next();
System.out.print(em + " earns $");System.out.println(em.earnings());
}}
}%java EmployeeTestUse built-in iterator:Manager: Bill earns $800.0
Commission worker:Newt earns $405.999625Piece worker: Al earns $500.0Hourly worker: Babara earns $550.0Manager: Peter earns $1200.0Commission worker:Margret earns $611.01375Piece worker: Mark earns $1498.5Hourly worker: William earns $1562.5
-
8/20/2019 Design Pattern QA
103/171
The above example also shows a dynamic binding feature which is
popular in Object-Oriented realm.
If you want to pick up a specific object from the aggregated list,
you may use the following code.
while(iterator.hasNext()) {Employee em = (Employee)iterator.next();if (em instanceof Manager) {
System.out.print(em + " earns $");System.out.println(em.earnings());
}}
The above list can also be replaced by an array and achieve the
same result.
e.
Mediator
Definition
Define an object that encapsulates details and other objects interact
with such object. The relationships are loosely decoupled.
Where to use & benefits
Partition a system into pieces or small objects.
Centralize control to manipulate participating objects(a.k.a
colleagues)
Clarify the complex relationship by providing a board
committee.
Limit subclasses.
-
8/20/2019 Design Pattern QA
104/171
Improve objects reusabilities.
Simplify object protocols.
The relationship between the control class and other
partic