行為型模式
- 11種行為模式的關系:
- 第一類: 通過父類與子類的關系進行實作
- 第二類: 通過兩個類之間的關系進行實作
- 第三類: 通過類的狀态進行實作
- 第四類: 通過中間類進行實作
深入了解設計模式!詳細解析11種行為型模式行為型模式
政策模式(Strategy)
- 政策模式:
- 定義了一系列算法,并将每個算法封裝起來,可以互相替換,算法的變化不會影響到使用算法的使用者
- 設計一個接口,為一系列實作類提供統一的方法,多個實作類實作該接口
- 設計一個抽象類(選用,作為輔助類),提供輔助函數
- ICalculator接口提供統一的方法
- AbstractCalculator是抽象輔助類,提供輔助方法
- ICalculator
public interface ICalculator{
public int calculate(String exp);
}
- AbstractCalculator
public abstract class AbstractCalcuator{
public int[] split(String exp,String opt){
String array[]=exp.split(opt);
int arrayInt[]=new int[2];
arrayInt[0]=Integer.parseInt(array[0]);
arrayInt[1]=Integer.parseInt(array[1]);
return arrayInt;
}
}
- Plus
public class Plus extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,"\\+");
return arrayInt[0]+arrayInt[1];
}
}
- Minus
public class Minus extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,"-");
return arrayInt[0]-arrayInt[1];
}
}
- Multiply
public class Multiply extends AbstractCalculator implements ICalculator{
@Override
public int calculate(String exp){
int arrayInt[]=split(exp,"\\*");
return arrayInt[0]*arrayInt[1];
}
}
- StrategyTest
public class StrategyTest{
public static void mian(String[] args){
String exp="2+8";
ICalculator cal=new Plus();
int result=cal.calculate(exp);
System.out.println(result);
}
}
- 政策模式的決定權在于使用者:
- 系統本身提供不同算法的實作
- 新增或删除算法
- 對各種算法做封裝
- 政策模式多用在算法決策系統中,外部使用者隻需要決定使用哪一個算法即可
模闆方法模式(Template Method)
- 模闆方法模式:
- 一個抽象類中,定義一個主方法
- 再定義無數個方法,可以是抽象的,也可以是實際的方法
- 定義一個子類,繼承抽象類,重寫抽象類中的方法
- 通過調用抽象類,實作對子類的調用
深入了解設計模式!詳細解析11種行為型模式行為型模式 - AbstractCalculator類中定義一個主方法calculate()
- calculate() 調用split() 等
- Plus和Minus分别繼承AbstractCalculator類
- 通過對AbstractCalculator的調用實作對子類的調用
public abstract class AbstractCalculator{
/* 主方法,實作對本類的其它方法的調用 */
public final int calculate(String exp,String opt){
int array[]=split(exp,opt)
return calculate(array[0],array[1]);
}
/* 抽象方法,需要子類進行重寫 */
abstract public int calculate(int num1,int num2);
public int[] split(String exp,String opt){
String array[]=exp.split(opt);
int arrayInt[]=new int[2];
arrayInt[0]=Integer.parseInt(array[0]);
arrayInt[1]=Integer.parseInt(array[1]);
return arrayInt;
}
}
- Plus
public class Plus extends AbstractCalculator{
@Override
public int calculate(int num1,int num2){
return num1+num2;
}
}
- StrategyTest
public class StrategyTest{
public static void main(String[] args){
String exp="8+8";
AbstractCalculator cal=new Plus();
int result=cal.calculate(exp,"\\+");
System.out.println(result);
}
}
Test的執行過程:
- 首先将exp和"\ \ +"做參數,調用AbstractCalculator類裡的calculate(String,String)方法
- 在calculate(String,String) 裡調用同類的split()
- 然後再調用calculate(int,int) 方法
- 從這個方法進入到子類中
- 執行完return num1+num2之後,将值傳回到AbstractCalculator類,指派給result, 列印出來
觀察者模式(Observer)
- 觀察者模式是類與類之間的關系,不涉及繼承
- 觀察者模式類似郵件訂閱和RSS訂閱:
- 當你訂閱了該内容,如果後續有更新,會及時接收到通知
- 觀察者模式: 當一個對象變化時,依賴該對象的對象都會接收到通知,并且随着變化.對象之間是一對多的關系
- MySubject類是主對象
- Observer1和Observer2是依賴于MySubject的對象
- 當MySubject變化時 ,Observer1和Observer2必然變化
- AbstractSubject類中定義者需要監控的對象清單,可以對這些對象進行修改:增加或者删除被監控對象
- 當MySubject變化時 ,AbstractSubject類負責通知在清單記憶體在的對象
- Observer
public interface Observer{
public void update();
}
- Observer1
public class Observer1 implements Observer{
@Override
public void update(){
System.out.println("Observer1 has received!");
}
}
- Observer2
public class Observer2 implements Observer{
@Override
public void update(){
System.out.println("Observer2 has received!");
}
}
- Subject
public interface Subject{
/* 增加觀察者 */
public void add(Observer observer);
/* 删除觀察者 */
public void del(Observer observer);
/* 通知所有觀察者 */
public void notifyObservers();
/* 自身的操作 */
public void operation();
}
- AbstractSubject
public abstract class AbstractSubject implements Subject{
private Vector<Observer> vector=new Vector<Observer>();
@Override
public void add(Observer observer){
vector.add(observer);
}
@Override
public void del(Observer observer){
vector.remove(observer);
}
@Override
public void notifyObservers(){
Enumeration<Observer> enumo=vector.elements();
while(enumo.hasMoreElements()){
enumo.nextElement().update();
}
}
}
- MySubject
public class MySubject extends AbstractSubject{
@Override
public void operation(){
System.out.println("update self!");
notifyObservers();
}
}
- ObserverTest
public class ObserverTest{
public static void main(String[] args){
Subject sub=new MySubject();
sub.add(new Observer1());
sub.add(new Observer2());
sub.operation();
}
}
- 觀察者模式根據關系圖,建立項目,使用代碼按照總體思路走一遍,這樣容易了解觀察者模式的思想
疊代子模式(Iterator)
- 疊代子模式是類與類之間的關系,不涉及繼承
- 疊代子模式: 順序通路聚集中的對象. 包含兩層意思:
- 聚集對象: 需要周遊的對象
- 疊代器對象: 用于對聚集對象進行周遊通路
- MyCollection中定義了集合的一些操作
- MyIterator中定義了一系列疊代操作,并且持有Collection執行個體
- Collection
public interface Collection{
public Iterator iterator();
/* 取得集合元素 */
public Object get(int i);
/* 取得集合大小 */
public int size();
}
- Iterator
public interface Iterator{
// 前移
puublic Object previous();
// 後移
public Object next();
public boolean hasNext();
// 取得第一個元素
public Object first();
}
- MyCollection
public class MyCollection implements Collection{
public String string[]={"A","B","C","D","E"};
@Override
public Iterator iterator(){
return new MyIterator(this);
}
@Override
public Object get(int i){
return string[i];
}
@Override
public int size(){
return string.length;
}
}
- MyIterator
public class MyIterator implements Iterator{
private Collection collection;
private int pos=-1;
public MyIterator(Collection collection){
this.collection=collection;
}
@Override
pbulic Object previous(){
if(pos>0){
pos--;
}
return collection.get(pos);
}
@Override
public Object next(){
if(pos<collection.size()-1){
pos++;
}
return collection.get(pos);
}
@Override
public Object hasNext(){
if(pos<collection.size()-1){
return true;
}else{
return false;
}
}
@Override
public Object first(){
pos=0;
return collection.get(pos);
}
}
- Test
public class Test{
Collection collection=new MyCollection();
Iterator it=collection.iterator();
whhile(it.hasNext()){
System.out.println(it.next());
}
}
- JDK中各個類都是這些基本的集合,加上一些設計模式,再加一些優化組合到一起的,隻要掌握這些,可以寫出自定義的集合類,甚至架構
責任鍊模式(Chain of Responsibility)
- 類與類之間的關系,不涉及繼承
- 責任鍊模式:
- 有多個對象,每個對象持有對下一個對象的引用,這樣形成一條鍊,直到某個對象決定處理該請求
- 請求發出者并不清楚到底最終哪個對象會處理該請求
- 責任鍊模式可以實作 :在隐瞞用戶端的情況下,對系統進行動态調整
- Abstracthandler類提供了get和set方法,友善MyHandler類設定和修改引用對象
- MyHandler類是核心,執行個體化後生成一系列互相持有的對象,構成一條鍊
- Handler
public interface Handler{
public void operator();
}
- AbstractHandler
public abstract class AbstractHandler{
private Handler handler;
private Handler getHandler(){
return handler;
}
private void setHandler(Handler handler){
this.handler=handler;
}
}
- MyHandler
public class MyHandler extends AbstractHandler implements Handler{
private String name;
public MyHandler(String name){
this.name=name;
}
@Override
public void operator(){
System.out.println(name+"deal!");
if(getHandler()!=null){
getHandler().operator();
}
}
}
- Test
public class Test{
public static void main(String[] args){
MyHandler h1=new MyHandler("h1");
MyHanlder h2=new MyHandler("h2");
MyHandler h3=new MyHandler("h3");
h1.setHandler(h2);
h2.setHandler(h3);
h1.operator();
}
}
- 連結上的請求可以是一條鍊,可以是一個樹,還可以是一個環
- 模式本身不受這個限制,需要自定義實作
- 在同一個時刻,指令隻允許由一個對象傳給另一個對象,不允許傳給多個對象
指令模式(Command)
- 指令模式了解示例:
- 司令員的作用是: 發出密碼
- 密碼經過傳遞,傳到士兵耳中,士兵去執行
- 這個過程好在:司令,密碼,士兵三者互相解藕
- 任何一方都不用去依賴其它方,隻需要做好自身的事即可
- 司令員要的是結果,不會去關注士兵到底怎麼實作的
深入了解設計模式!詳細解析11種行為型模式行為型模式 - Invoker是調用者(司令員)
- Receiver是被調用者(士兵)
- MyCommand是指令,實作了Command接口,持有接收對象
- Command
public interface Command{
public void exe();
}
- MyCommand
public class MyCommand implements Command{
private Receiver receiver;
public MyCommand(Receiver receiver){
this.receiver=receiver;
}
@Override
public void exe(){
receiver.action();
}
}
- Receiver
public class Receiver{
public void action(){
System.out.println("Command Received!");
}
}
- Invoker
public class Invoker{
private Command command;
public Invoker(Command command){
this.command=command;
}
public void action(){
command.exe();
}
}
- Test
public class Test{
public static void main(String[] args){
Receiver receiver=new Receiver();
Command cmd=new MyCommand(receiver);
Invoker Invoker=new Invoker(cmd);
invoker.action();
}
}
- 指令模式的目的: 達到指令的發出者和執行者之間的解耦,實作請求和執行分開
- Struts其實就是一種将請求和呈現分離的技術,使用了指令模式的設計思想
備忘錄模式(Memento)
- 備忘錄模式 :主要目的是儲存一個對象的某個狀态,以便在适當的時候恢複對象
- 備忘錄模式了解:
- 假設有原始類A,A中有各種屬性,A可以決定需要備份的屬性
- 備忘錄類B用來存儲A的一些内部狀态
- 類C用來存儲備忘錄,并且隻能存儲,不能進行修改等操作
- Original類是原始類,裡面有需要儲存的屬性value及建立一個備忘錄類,用來儲存value值
- Memento類是備忘錄類
- Storage類是存儲備忘錄的類,持有Memento類的執行個體
- Original
public class Original{
private String value;
private String getValue(){
return value;
}
private void setValue(String value){
this.value=value;
}
public Original(String value){
this.value=value;
}
public Memento createMemento(){
return new Memento(value);
}
public void restoreMemento(Memento memento){
this.value=memento.getValue();
}
}
- Memento
public class Memento{
private String value;
public Memento(String value){
this.value=value;
}
public String getValue(){
return value;
}
public void setValue(String value){
this.value=value;
}
}
- Storage
public class Storage{
private Memento memento;
public Storage(Memento memento){
this.memento=memento;
}
public Memento getMemento(){
return memento;
}
public void setMemento(Memento memento){
this.memento=memento;
}
}
- Test
public class Test{
public static void main(String[] args){
// 建立原始類
Original original=new Original("egg");
// 建立備忘錄
Storage storage=new Storage(original.createMemento());
// 修改原始類的狀态
System.out.println("初始狀态為:"+original.getValue());
original.setValue("bulk");
System.out.println("修改後的狀态:"+original.getValue());
// 恢複原始類的狀态
original.restoreMemento(storage.getMemento());
System.out.println("恢複後的狀态為:"+original.getValue());
}
}
- 建立原始類時 ,value被初始化為egg, 後經過修改,将value值修改為bulk, 最後進行恢複狀态,結果成功恢複
狀态模式(State)
- 狀态模式 :當對象的狀态改變時,同時改變對象的行為
- 狀态模式了解示例:
- QQ有幾種不同的狀态:線上,隐身,忙碌等
- 每個狀态對應不同的操作,而且好友也能看到相關的狀态
- 狀态模式包括兩層含義:
- 可以通過改變狀态來獲得不同的行為
- 對象狀态的變化可以被發現
- State類是個狀态類
- Context類可以實作切換
- State
public class State{
private String value;
private String getValue(){
return value;
}
private void setValue(String value){
this.value=value;
}
public void method1(){
System.out.println("Execute the first opt!");
}
public void method2(){
System.out.println("Execute the second opt!");
}
}
- Context
public class Context{
private State state;
private Context(State state){
this.state=state;
}
public State getState(){
return state;
}
public void setState(){
this.state=state;
}
public void method(){
if(state.getValue().equals("state1")){
state.method1();
}else if(state.getValue().equals("state2")){
state.method2();
}
}
}
- Test
public class Test{
public static void main(String[] args){
State state=new State();
Context context=new Context(state);
// 設定第一種狀态
state.setValue("state1");
context.method();
// 設定第二種狀态
state.setValue("state2");
context.method();
}
}
- 狀态模式的應用場景十分廣泛:在做網站的時候,希望根據對象的屬性,差別一些功能等,比如說權限控制等等
通路者模式(Visitor)
- 通路者模式将資料結構和作用于結構上的操作解耦,使得操作集合可以相對自由地進行演化
- 通路者模式适用于資料結構相對穩定,算法容易變化的系統:
- 通路者模式使得算法操作增加變得更加容易
- 若系統資料結構對象易于變化,經常有新的對象增加進來,則不适合使用通路者模式
- 通路者模式的特點:
- 優點: 增加操作容易
- 增加操作意味着增加新的通路者
- 通路者模式将有關行為集中到一個通路者對象中, 這些行為的改變不影響系統資料結構
- 缺點: 增加新的資料結構很困難
- 優點: 增加操作容易
- 通路者模式 :是一種分離對象資料結構和行為的方法,通過這種分離,可以達到為一個被通路者動态添加新的操作而無需做任何修改的效果
- 一個Visitor類,存放要通路的對象
- Subject類中有accept方法,接收将要通路的對象 ,getSubject() 擷取将要被通路的屬性
- Visitor
public interface Visitor{
public void visit(Subject sub);
}
- MyVisitor
public class MyVisitor implements Visitor{
@Override
public void visit(Subject sub){
System.out.println("visit the subject:"+sub.getSubject());
}
}
- Subject
public interface Subject{
public void accept(Visitor visitor);
public String getSubject();
}
- MySubject
public class MySubject implements Subject{
@Override
public void accept(Visitor visitor){
visitor.visit(this);
}
@Override
public String getSubject(){
return "love";
}
}
- Test
public class Test{
public static void main(String[] args){
Visitor visitor=new MyVisitor();
Subject sub=new MySubject();
sub.accept(visitor);
}
}
- 訪客模式适用場景:
- 如果要為一個現有的類增加新功能:
- 新功能是否會與現有功能出現相容性問題
- 以後會不會還有新功能需要添加
- 如果類不允許修改代碼怎麼處理
- 這些問題最好的解決辦法就是訪客模式
- 通路者模式适用于資料結構相對穩定的系統,将資料結構和算法解耦
- 如果要為一個現有的類增加新功能:
中介者模式(Mediator)
- 中介者模式是用來降低類與類之間的耦合的:
- 類與類之間有依賴關系的話,不利于功能的拓展和維護
- 因為隻要修改一個對象,其它關聯的對象都要進行修改
- 中介者模式: 隻需要關心Mediator類的關系,具體類與類之間的關系及排程交給Mediator, 與Spring容器的作用類似
- User類統一接口
- User1和User2分别是不同的對象:
- 二者之間有關聯
- 如果不采用中介者模式.則需要二者互相持有引用,這樣二者的耦合度很高
- 為了解耦,引入了Mediator類,提供統一接口
- MyMediator為實作類:
- 持有User1和User2的執行個體,用來實作對User1和User2的控制
- 這樣User1和User2兩個對象就可以互相獨立,隻需保持與Mediator之間的關系就可以
- Mediator類用來維護
- Mediator
public interface Mediator{
public void createMediator();
public void workAll();
}
- MyMediator
public class MyMediator implements Mediator{
private User user1;
private User user2;
public User getUser1(){
return user1;
}
public User getUser2(){
return user2;
}
@Override
public void createMediator(){
user1=new User1(this);
user2=new User2(this);
}
@Override
public void workAll(){
user1.work();
user2.work();
}
}
- User
public abstract class User{
private Mediator mediator;
public Mediator getMediator(){
return mediator;
}
public User(Mediator mediator){
this.mediator=mediator;
}
public abstract void work();
}
- User1
public class User1 extends User{
public User1(Mediator mediator){
super(mediator);
}
@Override
public void work(){
System.out.println("user1 exe!");
}
}
- User2
public User2 extends User{
public User2(Mediator mediator){
super(mediator);
}
@Override
public void work(){
System.out.println("user2 exe!");
}
}
- Test
public class Test{
public static void main(String[] args){
Mediator mediator=new MyMediator();
mediator.createMediator();
mediator.workAll();
}
}
解釋器模式(Interpreter)
- 解釋器模式一般主要應用在OOP開發中的編譯器開發中,适用面比較窄
- Context類是一個上下文環境類
- Plus和Minus分别是計算的實作
- Expression
public interface Expression{
public int interpret(Context context);
}
- Plus
public class Plus implements Expression{
@Override
public int interpret(Context context){
return context.getNum1()+context.getNum2();
}
}
- Minus
public class Minus implements Expression{
@Override
public void interpret(Context context){
return context.getNum1()-context.getNum2();
}
}
- Context
public class Context{
private int num1;
private int num2;
public Context(int num1,int num2){
this.num1=num1;
this.num2=num2;
}
public int getNum1(){
return num1;
}
public void setNum1(int num1){
this.num1=num1;
}
public int getNum2(){
return num2;
}
public void setNum2(int num2){
this.num2=num2;
}
}
- Test
public class Test{
public static void main(String[] args){
// 計算 9+2-8
int result=new Minus().interpret((new Context(new Plus().interpret(new Context(9,2)),8)));
System.out.println(result);
}
}
- 解釋器模式是來用作各種各樣的解釋器