行為型設計模式(職責鏈模式,命令模式,中介者模式,觀察者模式,訪問者模式)
職責鏈模式
主要用於使多個物件都有機會處理請求,避免請求的的傳送者和接受者之間的耦合關係。在現實生活中我們多數遇到的是不純的責任鏈模式即每個物件都處理請求的一部分後再交給下家。而純的職責鏈模式則要求對於一個請求,要不處理要不就交給下家。具體理解呢。我們可以想一下“擊鼓傳花”的遊戲。或則是你幫你的同學傳一個紙條。如果傳給你你就看,否則就傳給下一個同學(嘻嘻)。比較容易理解,主要看一下類圖:
和相關程式碼實現:
public abstract class Handler { /** * 持有後繼的責任物件 */ protected Handler successor;/** * 示意處理請求的方法,雖然這個示意方法是沒有傳入引數的 * 但實際是可以傳入引數的,根據具體需要來選擇是否傳遞引數 */ public abstract void handleRequest(); /** * 取值方法 */ public Handler getSuccessor() { return successor; } /** * 賦值方法,設定後繼的責任物件 */ public void setSuccessor(Handler successor) {this.successor = successor; } }
具體處理者角色
public class ConcreteHandler extends Handler { /** * 處理方法,呼叫此方法處理請求 */ @Override public void handleRequest() { /** * 判斷是否有後繼的責任物件 * 如果有,就轉發請求給後繼的責任物件 * 如果沒有,則處理請求 */ if(getSuccessor() != null) { System.out.println("放過請求"); getSuccessor().handleRequest(); }else { System.out.println("處理請求"); } } }
客戶端類
public class Client { public static void main(String[] args) { //組裝責任鏈 Handler handler1 = new ConcreteHandler(); Handler handler2 = new ConcreteHandler(); handler1.setSuccessor(handler2); //提交請求 handler1.handleRequest(); } }命令模式。
主要用於把發出命令和執行命令的責任分開,委派給不同物件。怎麼理解呢?命令模式中請求的實現在接受者中實現但在最後客戶請求服務時。具體的實現是通過請求者呼叫具體命令角色來實現。舉個例子。錄音機(播放,倒帶,停止)三個功能
接收者角色,由錄音機類扮演
public class AudioPlayer { public void play(){ System.out.println("播放..."); } public void rewind(){ System.out.println("倒帶..."); } public void stop(){ System.out.println("停止..."); } }
抽象命令角色類
public interface Command { /** * 執行方法 */ public void execute(); }
具體命令角色類
public class PlayCommand implements Command { private AudioPlayer myAudio; public PlayCommand(AudioPlayer audioPlayer){ myAudio = audioPlayer; } /** * 執行方法 */ @Override public void execute() { myAudio.play(); } }
public class RewindCommand implements Command { private AudioPlayer myAudio; public RewindCommand(AudioPlayer audioPlayer){ myAudio = audioPlayer; } @Override public void execute() { myAudio.rewind(); } }
public class StopCommand implements Command { private AudioPlayer myAudio; public StopCommand(AudioPlayer audioPlayer){ myAudio = audioPlayer; } @Override public void execute() { myAudio.stop(); } }
請求者角色,由鍵盤類扮演
public class Keypad { private Command playCommand; private Command rewindCommand; private Command stopCommand; public void setPlayCommand(Command playCommand) { this.playCommand = playCommand; } public void setRewindCommand(Command rewindCommand) { this.rewindCommand = rewindCommand; } public void setStopCommand(Command stopCommand) { this.stopCommand = stopCommand; } /** * 執行播放方法 */ public void play(){ playCommand.execute(); } /** * 執行倒帶方法 */ public void rewind(){ rewindCommand.execute(); } /** * 執行播放方法 */ public void stop(){ stopCommand.execute(); } }
客戶端角色,由茱麗小女孩扮演
public class Julia { public static void main(String[]args){ //建立接收者物件 AudioPlayer audioPlayer = new AudioPlayer(); //建立命令物件 Command playCommand = new PlayCommand(audioPlayer); Command rewindCommand = new RewindCommand(audioPlayer); Command stopCommand = new StopCommand(audioPlayer); //建立請求者物件 Keypad keypad = new Keypad(); keypad.setPlayCommand(playCommand); keypad.setRewindCommand(rewindCommand); keypad.setStopCommand(stopCommand); //測試 keypad.play(); keypad.rewind(); keypad.stop(); keypad.play(); keypad.stop(); } }在例子之後我們再看類圖是不就感覺簡單一些
中介者模式
使用場景:集中負責維護物件模型的關係完整性 以及需要 封裝物件間互動方式的時候.
其實MVC中的controller就是一種Mediator,是UI層 和後端應用sevice層間的中介者。中介者將互動的複雜性變為中介者的複雜性
在此寫了7個java類來描述說明Mediator設計模式的實現方式;
1、 Colleague.java 互動物件的抽象類
2、 Colleague1.java 互動物件1
3、 Colleague2.java 互動物件2
4、 Colleague3.java 互動物件3
5、 Mediator.java 中介者抽象類
6、 ConcreteMediator.java 具體的中介者
7、 MediatorTest.java 帶有main方法的測試類
=============== 1、 Colleague.java
互動物件的抽象類,定義了中介者的注入方法 、互動的行為方法
package mediator;
public abstract class Colleague {
//中介者
private Mediator mediator;
public Mediator getMediator() {
return mediator;
}
public Colleague(Mediator m) {
mediator = m;
}
//訊息
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
//傳送訊息
public abstract void sendMsg();
//收到訊息
public abstract void getMsg(String msg);
//傳送訊息
public void sendMsg(String msg) {
this.message = msg;
mediator.action(this);
}
}
=============== 1 end
=============== 2、 Colleague1.java
package mediator;
public class Colleague1 extends Colleague {
public Colleague1(Mediator m) {
super(m);
}
public void getMsg(String msg) {
System.out.println("Colleague1 has got the message -'" + msg + "'");
}
public void sendMsg() {
System.out.println("Colleague1 has send the message '" + getMessage() + "'");
}
}
=============== 2 end
=============== 3、 Colleague2.java
package mediator;
public class Colleague2 extends Colleague {
public Colleague2(Mediator m) {
super(m);
}
public void getMsg(String msg) {
System.out.println("Colleague2 has got the message -'" + msg + "'");
}
public void sendMsg() {
System.out.println("Colleague2 has send the message '" + getMessage() + "'");
}
}
=============== 3 end
=============== 4、 Colleague3.java
package mediator;
public class Colleague3 extends Colleague {
public Colleague3(Mediator m) {
super(m);
}
public void getMsg(String msg) {
System.out.println("Colleague3 has got the message -'" + msg + "'");
}
public void sendMsg() {
System.out.println("Colleague3 has send the message '" + getMessage() + "'");
}
}
=============== 4 end
=============== 5、 Mediator.java
package mediator;
abstract class Mediator {
//Mediator針對Colleague的一個互動行為
public abstract void action(Colleague sender);
//加入Colleague物件
public abstract void addCollegue(Colleague colleague);
}
=============== 5 end
=============== 6、 ConcreteMediator.java
具體的中介者,負責管理Colleague物件間的關係、以及Colleague物件間的互動
package mediator;
import java.util.ArrayList;
import java.util.List;
public class ConcreteMediator extends Mediator {
private List<Colleague> colleagues = new ArrayList<Colleague>(0);
public void addCollegue(Colleague colleague) {
colleagues.add(colleague);
}
public void action(Colleague actor) {
String msg = actor.getMessage();
//send msg
for (Colleague colleague : colleagues) {
if(colleague.equals(actor)){
colleague.sendMsg();
break;
}
}
//get msg
for (Colleague colleague : colleagues) {
if(colleague.equals(actor))
continue;
colleague.getMsg(msg);
}
}
}
=============== 6 end
=============== 7、 MediatorTest.java
package mediator;
public class MediatorTest {
public static void main(String[] args) {
//生成中介者 並注入到各個Colleague物件中
Mediator mediator = new ConcreteMediator();
Colleague colleague1 = new Colleague1(mediator);
Colleague colleague2 = new Colleague2(mediator);
Colleague colleague3 = new Colleague3(mediator);
//註冊物件到中介
mediator.addCollegue(colleague1);
mediator.addCollegue(colleague2);
mediator.addCollegue(colleague3);
//Colleague1 觸發行為
colleague1.sendMsg("Hi,it's time to lunch. Let's go!");
System.out.println();
//Colleague2 觸發行為
colleague2.sendMsg("Is anybody here!");
System.out.println();
//Colleague3 觸發行為
colleague3.sendMsg("Wait!I will lunch off right away.");
System.out.println();
}
}
觀察者模式
觀察者模式又稱為釋出訂閱模式,模型檢視模式,源-監聽器模式。它定義一種一對多的依賴關係,讓多個觀察者同時監聽一個主題物件。這個主題物件發生改變時,所有觀察者做出相應變化。例如我們買衣服。我們去買衣服結果沒貨。我們會把自己的聯絡方式留下來(註冊),等有貨時商家通知你。其實這就是一個觀察者模式。我們以及其他買衣服者是觀察者,商家是被觀察者。商家狀態改變(有衣服),通知觀察者,觀察者也做出相應變化(去買衣服)。一個簡單的Java例子:
//抽象觀察者角色 public interface Watcher { public void update(String str); }
然後定義抽象的主題角色,即抽象的被觀察者,在其中宣告方法(新增、移除觀察者,通知觀察者):
//抽象主題角色,watched:被觀察 public interface Watched { public void addWatcher(Watcher watcher); public void removeWatcher(Watcher watcher); public void notifyWatchers(String str); }
然後定義具體的觀察者:
public class ConcreteWatcher implements Watcher { @Override public void update(String str) { System.out.println(str); } }
之後是具體的主題角色:
import java.util.ArrayList; import java.util.List; public class ConcreteWatched implements Watched { // 存放觀察者 private List<Watcher> list = new ArrayList<Watcher>(); @Override public void addWatcher(Watcher watcher) { list.add(watcher); } @Override public void removeWatcher(Watcher watcher) { list.remove(watcher); } @Override public void notifyWatchers(String str) { // 自動呼叫實際上是主題進行呼叫的 for (Watcher watcher : list) { watcher.update(str); } } }
編寫測試類:
public class Test { public static void main(String[] args) { Watched girl = new ConcreteWatched(); Watcher watcher1 = new ConcreteWatcher(); Watcher watcher2 = new ConcreteWatcher(); Watcher watcher3 = new ConcreteWatcher(); girl.addWatcher(watcher1); girl.addWatcher(watcher2); girl.addWatcher(watcher3); girl.notifyWatchers("開心"); } }訪問者模式
訪問者模式適用於資料結構相對穩定的系統,它將演算法與物件結構分離開,是操作能相對自由的演化。看一下類圖
:
public abstract class Customer {
private String customerId;
private String name;
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 接受訪問者的訪問
* @param visitor
*/
public abstract void accept(Visitor visitor);
}
/**
* 企業客戶
*/
public class EnterpriseCustomer extends Customer {
private String linkman;
private String linkTelephone;
private String registerAddress;
public String getLinkman() {
return linkman;
}
public void setLinkman(String linkman) {
this.linkman = linkman;
}
public String getLinkTelephone() {
return linkTelephone;
}
public void setLinkTelephone(String linkTelephone) {
this.linkTelephone = linkTelephone;
}
public String getRegisterAddress() {
return registerAddress;
}
public void setRegisterAddress(String registerAddress) {
this.registerAddress = registerAddress;
}
@Override
public void accept(Visitor visitor) {
//回撥訪問者物件的方法
visitor.visitEnterpriseCustomer(this);
}
}
/**
* 個人客戶
*/
public class PersonalCustomer extends Customer {
private String telephone;
private int age;
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void accept(Visitor visitor) {
//回撥訪問者物件的方法
visitor.visitPersonalCustomer(this);
}
}
/**
* 訪問者介面
*/
public interface Visitor {
/**
* 訪問企業客戶,相當於給企業客戶新增訪問者功能
* @param ec 企業客戶物件
*/
public void visitEnterpriseCustomer(EnterpriseCustomer ec);
/**
* 訪問個人客戶,相當於給個人客戶新增訪問者的功能
* @param pc
*/
public void visitPersonalCustomer(PersonalCustomer pc);
}
/**
* 具體的訪問者,實現對客戶的偏好分析
*/
public class PredilectionAnalyzeVisitor implements Visitor {
@Override
public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
// TODO 根據以往的購買歷史、潛在購買意向,以及客戶所在行業的發展趨勢、客戶的發展趨勢等的分析
System.out.println("現在對企業客戶" + ec.getName() + "進行產品偏好分析");
}
@Override
public void visitPersonalCustomer(PersonalCustomer pc) {
System.out.println("現在對個人客戶" + pc.getName() + "進行產品偏好分析");
}
}
/**
* 具體的訪問者,實現客戶提出服務請求的功能
*/
public class ServiceRequestVisitor implements Visitor {
@Override
public void visitEnterpriseCustomer(EnterpriseCustomer ec) {
// TODO 企業客戶提出的具體服務請求
System.out.println(ec.getName() + "企業提出服務請求");
}
@Override
public void visitPersonalCustomer(PersonalCustomer pc) {
// TODO 個人客戶提