終於有功夫坐下來把所有Design Pattern好好整理一通了,這可是個盤算了快十年的想法了。
===========================================================================================================
主要參考資料來源:
1. Design Patterns Explained -- Alan Shalloway/James Trott
2. Design Patterns -- The "Gang of Four"
3. 解道 http://www.jdon.com/designpatterns/
4. http://en.wikipedia.org/wiki/Design_Patterns
5. http://www.forestandthetrees.com/designPatterns/
Creational Design Pattern
Singleton,Abstract Factory, Builder, Factory Method, Prototype================================================================================================================
Singleton Design Pattern
對於某個對象,在系統中需要並且只需要一個該對象的實例的情況下使用該模式,常見的象Configuration, Log等。
Prototype Design Pattern
在Java中,clone函數用於實現Prototype模式Factory Method Design Pattern
工廠方法模式:用一個工廠生產同一類型的不同具體對象。如下面這個例子,每當程序需要讀一個Image,它都需要創建一個與該Image類型相對應的Reader。創建Reader的邏輯可以使用工廠方法模式。
public class ImageReaderFactory
{
public static ImageReader getImageReader(InputStream is)
{
int imageType = determineImageType(is);
switch(imageType)
{
case ImageReaderFactory.GIF:
return new GifReader(is);
case ImageReaderFactory.JPEG:
return new JpegReader(is);
// etc.
}
}
}
Abstract Factory Design Pattern
這個設計模式用於封裝同一類型的不同工廠。下面這個例子是典型的Abstract Factory Pattern. 與上面的工廠模式最大的不同是工廠模式是一個工廠生產不同的具體對象,而Abstract Factory是不同的具體工廠生產不同的對象
interface GUIFactory {
public Button createButton();
}
class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}
}
class OSXFactory implements GUIFactory {
public Button createButton() {
return new OSXButton();
}
}
interface Button {
public void paint();
}
class WinButton implements Button {
public void paint() {
System.out.println("I'm a WinButton");
}
}
class OSXButton implements Button {
public void paint() {
System.out.println("I'm an OSXButton");
}
}
class Application {
public Application(GUIFactory factory) {
Button button = factory.createButton();
button.paint();
}
}
public class ApplicationRunner {
public static void main(String[] args) {
new Application(createOsSpecificFactory());
}
public static GUIFactory createOsSpecificFactory() {
int sys = readFromConfigFile("OS_TYPE");
if (sys == 0) {
return new WinFactory();
} else {
return new OSXFactory();
}
}
}
Builder Design Pattern
注重抽象對象的構造細節,不同的builder採用不同的構造過程生產產品
public class Pizza { // product
private final String dough;
private final String sauce;
private final String topping;
Pizza(PizzaBuilder builder) {
dough = builder.getDough();
sauce = builder.getSauce();
topping = builder.getTopping();
}
@Override
public String toString() {
return "Dough:" + dough + " Topping:" + topping + " Sauce:" + sauce;
}
}
public class PizzaBuilder {
String dough;
String sauce;
String topping;
public PizzaBuilder withDough(String dough) {
this.dough = dough;
return this;
}
public PizzaBuilder withSauce(String sauce) {
this.sauce = sauce;
return this;
}
public PizzaBuilder withTopping(String topping) {
this.topping = topping;
return this;
}
public String getDough() {
return dough;
}
public String getSauce() {
return sauce;
}
public String getTopping() {
return topping;
}
public Pizza build() {
return new Pizza(this);
}}
public class PizzaBuilderExample {
public static void main(String[] args) {
PizzaBuilder hawaiianPizzaBuilder = new PizzaBuilder().withDough("cross").withTopping("ham+pineapple").withSauce("mild");
Pizza hawaiianPizza = hawaiianPizzaBuilder.build();
System.out.println("Hawaiian Pizza: "+hawaiianPizza);
}
}
Structural Design Pattern
Adaptor, Bridge, Composite, Facade, Proxy-virtual, Decorator,Flyweight
=============================================================================================================
Decorator Design Pattern
動態給一個對象添加一些額外的職責,使用Decorator模式相比用生成子類方式達到功能的擴充顯得更爲靈活.
爲什麼使用Decorator?
我們通常可以使用繼承來實現功能的拓展,如果這些需要拓展的功能的種類很繁多,那麼勢必生成很多子類,增加系統的複雜性,同時,使用繼承實現功能拓展,我們必須可預見這些拓展功能,這些功能是編譯時就確定了,是靜態的.
使用Decorator的理由是:這些功能需要由用戶動態決定加入的方式和時機.Decorator提供了"即插即用"的方法,在運行期間決定何時增加何種功能. Java API中BufferedReader即是Decorator的一個例子
賣咖啡的例子
// The Coffee Interface defines the functionality of Coffee implemented by decorator
public interface Coffee {
public double getCost(); // returns the cost of the coffee
public String getIngredients(); // returns the ingredients of the coffee
}
// implementation of a simple coffee without any extra ingredients
public class SimpleCoffee implements Coffee {
public double getCost() {
return 1;
}
public String getIngredients() {
return "Coffee";
}
}
下面是各種Decorator
// abstract decorator class - note that it implements Coffee interface
abstract public class CoffeeDecorator implements Coffee {
protected final Coffee decoratedCoffee;
protected String ingredientSeparator = ", ";
public CoffeeDecorator(Coffee decoratedCoffee) {
this.decoratedCoffee = decoratedCoffee;
}
public double getCost() { // implementing methods of the interface
return decoratedCoffee.getCost();
}
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
// Decorator Milk that mixes milk with coffee
// note it extends CoffeeDecorator
public class Milk extends CoffeeDecorator {
public Milk(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() { // overriding methods defined in the abstract superclass
return super.getCost() + 0.5;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Milk";
}
}
// Decorator Whip that mixes whip with coffee
// note it extends CoffeeDecorator
public class Whip extends CoffeeDecorator {
public Whip(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() {
return super.getCost() + 0.7;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Whip";
}
}
<pre name="code" class="java">// Decorator Sprinkles that mixes sprinkles with coffee
// note it extends CoffeeDecorator
public class Sprinkles extends CoffeeDecorator {
public Sprinkles(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() {
return super.getCost() + 0.2;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Sprinkles";
}
}
使用: public class Main{
public static void main(String[] args) {
Coffee c = new SimpleCoffee();
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Milk(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Sprinkles(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Whip(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); // Note that you can also stack more than one decorator of the same type
c = new Sprinkles(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
}
}
運行結果
Cost: 1.0; Ingredients: Coffee
Cost: 1.5; Ingredients: Coffee, Milk
Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles
Cost: 2.4; Ingredients: Coffee, Milk, Sprinkles, Whip
Cost: 2.6; Ingredients: Coffee, Milk, Sprinkles, Whip, Sprinkles
Proxy Design Pattern
爲其他對象提供一種代理以控制對這個對象的訪問。有兩種用法:一種是基於性能(內存或速度)考慮,如remote proxy,另外一種是功能增添,比如授權機制控制,爲了控制不同的用戶對某個對象有不同的訪問權限,就可以使用proxy來控制。
interface Image {
void displayImage();
}
// on System A
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
//on System B
class ProxyImage implements Image {
private String filename;
private RealImage image;
public ProxyImage(String filename) {
this.filename = filename;
}
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
}
image.displayImage();
}
}
class ProxyExample {
public static void main(String[] args) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
image1.displayImage(); // loading necessary
image1.displayImage(); // loading unnecessary
image2.displayImage(); // loading necessary
image2.displayImage(); // loading unnecessary
image1.displayImage(); // loading unnecessary
}
}
Bridge Design Pattern
用於分離事物的抽象和其具體實現
class Client {
public static void main
(String argv[]) {
Shape r1, r2;
Drawing dp;
dp= new V1Drawing();
r1= new Rectangle(dp,1,1,2,2);
dp= new V2Drawing ();
r2= new Circle(dp,2,2,3);
r1.draw();
r2.draw();
}
}
//對象的抽象
abstract class Shape {
abstract public draw() ;
private Drawing _dp;
Shape (Drawing dp) {
_dp= dp;
}
public void drawLine (
double x1,double y1,
double x2,double y2) {
_dp.drawLine(x1,y1,x2,y2);
}
public void drawCircle (
double x,double y,double r) {
_dp.drawCircle(x,y,r);
}
}
//實現的抽象
abstract class Drawing {
abstract public void drawLine (
double x1, double y1,
double x2, double y2);
abstract public void drawCircle (
double x,double y,double r);
}
class V1Drawing extends Drawing {
public void drawLine (
double x1,double y1,
double x2,double y2) {
DP1.draw_a_line(x1,y1,x2,y2);
}
public void drawCircle (
double x,double y,double r) {
DP1.draw_a_circle(x,y,r);
}
}
class V2Drawing extends Drawing {
public void drawLine (
double x1,double y1,
double x2,double y2) {
// arguments are different in DP2
// and must be rearranged
DP2.drawline(x1,x2,y1,y2);
}
public void drawCircle (
double x, double y,double r) {
DP2.drawcircle(x,y,r);
}
}
class Rectangle extends Shape {
public Rectangle (
Drawing dp,
double x1,double y1,
double x2,double y2) {
super( dp) ;
_x1= x1; _x2= x2 ;
_y1= y1; _y2= y2;
}
public void draw () {
drawLine(_x1,_y1,_x2,_y1);
drawLine(_x2,_y1,_x2,_y2);
drawLine(_x2,_y2,_x1,_y2);
drawLine(_x1,_y2,_x1,_y1);
}
}
class Circle extends Shape {
public Circle (
Drawing dp,
double x,double y,double r) {
super( dp) ;
_x= x; _y= y; _r= r ;
}
public void draw () {
drawCircle(_x,_y,_r);
}
}
// We’ve been given the implementations for DP1 and DP2
class DP1 {
static public void draw_a_line (
double x1,double y1,
double x2,double y2) {
// implementation
}
static public void draw_a_circle(
double x,double y,double r) {
// implementation
}
}
class DP2 {
static public void drawline (
double x1,double x2,
double y1,double y2) {
// implementation
}
static public void drawcircle (
double x,double y,double r) {
// implementation
}
}
Composite Design Pattern
想到Composite就應該想到樹形結構圖。組合體內這些對象都有共同接口,當組合體一個對象的方法被調用執行時,Composite將遍歷整個樹形結構,尋找同樣包含這個方法的對象並實現調用執行。可以用牽一動百來形容。If programmers find that they are using multiple objects in the same way, and often have nearly identical code to handle each of them, then composite is
a good choice; it is less complex in this situation to treat primitives and composites as homogeneous.
Structure
Component
- is the abstraction for all components, including composite ones
- declares the interface for objects in the composition
- (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate
Leaf
- represents leaf objects in the composition .
- implements all Component methods
Composite
- represents a composite Component (component having children)
- implements methods to manipulate children
- implements all Component methods, generally by delegating them to its children
import java.util.List;
import java.util.ArrayList;
/** "Component" */
interface Graphic {
//Prints the graphic.
public void print();
}
/** "Composite" */
class CompositeGraphic implements Graphic {
//Collection of child graphics.
private List<Graphic> mChildGraphics = new ArrayList<Graphic>();
//Prints the graphic.
public void print() {
for (Graphic graphic : mChildGraphics) {
graphic.print();
}
}
//Adds the graphic to the composition.
public void add(Graphic graphic) {
mChildGraphics.add(graphic);
}
//Removes the graphic from the composition.
public void remove(Graphic graphic) {
mChildGraphics.remove(graphic);
}
}
/** "Leaf" */
class Ellipse implements Graphic {
//Prints the graphic.
public void print() {
System.out.println("Ellipse");
}
}
/** Client */
public class Program {
public static void main(String[] args) {
//Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
//Initialize three composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
//Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(graphic1);
graphic.add(graphic2);
//Prints the complete graphic (four times the string "Ellipse").
graphic.print();
}
}
Behavior Design Pattern
Chain of responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template method, Visitor
====================================================================================================
Chain
of Responsibility Pattern
用一系列類(classes)試圖處理一個請求request,這些類之間是一個鬆散的耦合,唯一共同點是在他們之間傳遞request. 也就是說,來了一個請求,A類先處理,如果沒有處理,就傳遞到B類處理,如果沒有處理,就傳遞到C類處理,就這樣象一個鏈條(chain)一樣傳遞下去--摘自:http://www.jdon.com/designpatterns/cor.htm。Javascript
和 Android框架的事件響應機制是Chain Of responsibility的最爲人熟知的例子。
Command Design Pattern
/*the Command interface*/
public interface Command {
void execute();
}
/*the Invoker class*/
import java.util.List;
import java.util.ArrayList;
public class Switch {
private List<Command> history = new ArrayList<Command>();
public Switch() {
}
public void storeAndExecute(Command cmd) {
this.history.add(cmd); // optional
cmd.execute();
}
}
/*the Receiver class*/
public class Light {
public Light() {
}
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
/*the Command for turning on the light - ConcreteCommand #1*/
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight = light;
}
public void execute(){
theLight.turnOn();
}
}
/*the Command for turning off the light - ConcreteCommand #2*/
public class FlipDownCommand implements Command {
private Light theLight;
public FlipDownCommand(Light light) {
this.theLight = light;
}
public void execute() {
theLight.turnOff();
}
}
/*The test class or client*/
public class PressSwitch {
public static void main(String[] args){
Light lamp = new Light();
Command switchUp = new FlipUpCommand(lamp);
Command switchDown = new FlipDownCommand(lamp);
Switch s = new Switch();
try {
if (args[0].equalsIgnoreCase("ON")) {
s.storeAndExecute(switchUp);
System.exit(0);
}
if (args[0].equalsIgnoreCase("OFF")) {
s.storeAndExecute(switchDown);
System.exit(0);
}
System.out.println("Argument \"ON\" or \"OFF\" is required.");
} catch (Exception e) {
System.out.println("Argument's required.");
}
}
}
Interpreter Design Pattern
Mediator Design Pattern
各個對象之間的交互操作非常多;每個對象的行爲操作都依賴彼此對方,修改一個對象的行爲,同時會涉及到修改很多其他對象的行爲,如果使用Mediator模式,可以使各個對象間的耦合鬆散,只需關心和 Mediator的關係,使多對多的關係變成了一對多的關係,可以降低系統的複雜性,提高可修改擴展性.
Mediator - 用於Colleague對象之間互相通信的接口
ConcreteMediator - Mediator的接口實現,協調Colleague對象之間的互相通信
ConcreteColleague - 通過Mediator與其他Colleague交互
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
//Colleague interface
interface Command {
void execute();
}
//Abstract Mediator
interface IMediator {
void book();
void view();
void search();
void registerView(BtnView v);
void registerSearch(BtnSearch s);
void registerBook(BtnBook b);
void registerDisplay(LblDisplay d);
}
//Concrete mediator
class Mediator implements IMediator {
BtnView btnView;
BtnSearch btnSearch;
BtnBook btnBook;
LblDisplay show;
//....
void registerView(BtnView v) {
btnView = v;
}
void registerSearch(BtnSearch s) {
btnSearch = s;
}
void registerBook(BtnBook b) {
btnBook = b;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void book() {
btnBook.setEnabled(false);
btnView.setEnabled(true);
btnSearch.setEnabled(true);
show.setText("booking...");
}
void view() {
btnView.setEnabled(false);
btnSearch.setEnabled(true);
btnBook.setEnabled(true);
show.setText("viewing...");
}
void search() {
btnSearch.setEnabled(false);
btnView.setEnabled(true);
btnBook.setEnabled(true);
show.setText("searching...");
}
}
//A concrete colleague
class BtnView extends JButton implements Command {
IMediator med;
BtnView(ActionListener al, IMediator m) {
super("View");
addActionListener(al);
med = m;
med.registerView(this);
}
public void execute() {
med.view();
}
}
//A concrete colleague
class BtnSearch extends JButton implements Command {
IMediator med;
BtnSearch(ActionListener al, IMediator m) {
super("Search");
addActionListener(al);
med = m;
med.registerSearch(this);
}
public void execute() {
med.search();
}
}
//A concrete colleague
class BtnBook extends JButton implements Command {
IMediator med;
BtnBook(ActionListener al, IMediator m) {
super("Book");
addActionListener(al);
med = m;
med.registerBook(this);
}
public void execute() {
med.book();
}
}
class LblDisplay extends JLabel {
IMediator med;
LblDisplay(IMediator m) {
super("Just start...");
med = m;
med.registerDisplay(this);
setFont(new Font("Arial", Font.BOLD, 24));
}
}
class MediatorDemo extends JFrame implements ActionListener {
IMediator med = new Mediator();
MediatorDemo() {
JPanel p = new JPanel();
p.add(new BtnView(this, med));
p.add(new BtnBook(this, med));
p.add(new BtnSearch(this, med));
getContentPane().add(new LblDisplay(med), "North");
getContentPane().add(p, "South");
setSize(400, 200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command) ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MediatorDemo();
}
}
Memento Design Pattern
memento模式:創建一個新的對象memento用來保存另外一個對象的內部狀態拷貝.這樣以後就可以將該對象恢復到原先保存的狀態.
import java.util.List;
import java.util.ArrayList;
class Originator {
private String state;
// The class could also contain additional data that is not part of the
// state saved in the memento.
public void set(String state) {
System.out.println("Originator: Setting state to " + state);
this.state = state;
}
public Memento saveToMemento() {
System.out.println("Originator: Saving to Memento.");
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
state = memento.getSavedState();
System.out.println("Originator: State after restoring from Memento: " + state);
}
public static class Memento {
private final String state;
private Memento(String stateToSave) {
state = stateToSave; //注意,在這裏,String是一個Immutable的對象,所以可以直接賦值,否則,需要state=stateToSave.clone();來確保state的不變性
}
private String getSavedState() {
return state;
}
}
}
class Caretaker {
public static void main(String[] args) {
List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
savedStates.add(originator.saveToMemento());
originator.set("State3");
// We can request multiple mementos, and choose which one to roll back to.
savedStates.add(originator.saveToMemento());
originator.set("State4");
originator.restoreFromMemento(savedStates.get(1));
}
}
Observer Design Pattern
Observer 模式其實就是我們在UI編程時經常使用的Listener機制。它定義了一種一對多的依賴關係,當一個對象的狀態發生變化,其所有依賴方都獲得通知並自動響應。
/* 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 ) {
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 the 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 );
// starts the event thread
Thread thread = new Thread(evSrc);
thread.start();
}
}
State Design Pattern
interface State {
void writeName(StateContext stateContext, String name);
}
class StateA implements State {
public void writeName(StateContext stateContext, String name) {
System.out.println(name.toLowerCase());
stateContext.setState(new StateB());
}
}
class StateB implements State {
private int count=0;
public void writeName(StateContext stateContext, String name){
System.out.println(name.toUpperCase());
// change state after StateB's writeName() gets invoked twice
if(++count>1) {
stateContext.setState(new StateA());
}
}
}
<pre name="code" class="java">//<span style="font-family:sans-serif;font-size:13px;color:#000000;font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); display: inline !important; float: none; ">The context class has a state variable which it instantiates in an initial state, in this case StateA.
</span>public class StateContext {
private State myState;
public StateContext() {
setState(new StateA());
}
// normally only called by classes implementing the State interface
public void setState(State newState) {
this.myState = newState;
}
public void writeName(String name) {
this.myState.writeName(this, name);
}
}
//And the usage:
public class TestClientState {
public static void main(String[] args) {
StateContext sc = new StateContext();
sc.writeName("Monday");
sc.writeName("Tuesday");
sc.writeName("Wednesday");
sc.writeName("Thursday");
sc.writeName("Saturday");
sc.writeName("Sunday");
}
}
Output: monday TUESDAY WEDNESDAY thursday SATURDAY SUNDAY
Strategy Design Pattern
Strategy 模式的意圖是使用聚合封裝(encapsulate)替代繼承來表示一個類的行爲,它根據事物發生時的上下文場景使用不同的業務規則或算法來解決問題。strategy模式將算法的分離
// The classes that implement a concrete strategy should implement this.
// The context class uses this to call the concrete strategy.
interface Strategy {
int execute(int a, int b);
}
// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyAdd's execute()");
return a + b; // Do an addition with a and b
}
}
class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategySubtract's execute()");
return a - b; // Do a subtraction with a and b
}
}
class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyMultiply's execute()");
return a * b; // Do a multiplication with a and b
}
}
// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
private Strategy strategy;
// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}
// Test application
class StrategyExample {
public static void main(String[] args) {
Context context;
// Three contexts following different strategies
context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);
}
}
Template Method Design Pattern
Template Method 模式其實就是Java中的抽象類和實現其抽象方法的派生類機制。
Visitor Design Pattern
作用於某個對象羣中各個對象的操作. 它可以使你在不改變這些對象本身的情況下,定義作用於這些對象的新操作.例子:
interface CarElementVisitor {
void visit(Wheel wheel);
void visit(Engine engine);
void visit(Body body);
void visit(Car car);
}
interface CarElement {
void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
class Wheel implements CarElement {
private String name;
public Wheel(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Body implements CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Car implements CarElement {
CarElement[] elements;
public CarElement[] getElements() {
return elements.clone(); // Return a copy of the array of references.
}
public Car() {
this.elements = new CarElement[]//create new Array of elements
{ new Wheel("front left"), new Wheel("front right"),
new Wheel("back left") , new Wheel("back right"),
new Body(), new Engine() };
}
public void accept(CarElementVisitor visitor) {
for(CarElement element : this.getElements()) {
element.accept(visitor);
}
visitor.visit(this);
}
}
class CarElementPrintVisitor implements CarElementVisitor {
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 CarElementDoVisitor implements CarElementVisitor {
public void visit(Wheel wheel) {
System.out.println("Kicking my " + wheel.getName() + " 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("Starting my car");
}
}
public class VisitorDemo {
static public void main(String[] args) {
Car car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
}