04-行為型模式

1. 模板方法模式*

模板方法模式:定義一個操作中的算法的骨架背率,而將一些步驟延遲到子類中栖秕,使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟

abstract class MySort {
    // 模板方法:
    // 提供了排序算法,但按什么順序排沒有實現(xiàn)
    public final void sort() {
        if (hook()) {
            orderBy();
        } else {
            System.out.println("默認排序規(guī)則");
        }
    }

    public abstract void orderBy();

    // 鉤子方法:默認為不做任何事情涕刚,子類可以視情況去選擇是否重寫
    public boolean hook() {
        return true;
    }
}

class AscSort extends MySort {
    @Override
    public void orderBy() {
        System.out.println("Asc");
    }
}

class DescSort extends MySort {
    @Override
    public void orderBy() {
        System.out.println("Desc");
    }
}

class DefaultSort extends MySort {
    @Override
    public void orderBy() {
    }

    @Override
    public boolean hook() {
        return false;
    }
}

public class TemplateMethodClient {
    public static void main(String[] args) {
        MySort ascSort = new AscSort();
        MySort descSort = new DescSort();
        MySort defaultSort = new DefaultSort();
        ascSort.sort();
        descSort.sort();
        defaultSort.sort();
    }
}

2. 命令模式

命令模式:將一個請求封裝為一個對象嗡综,讓發(fā)出命令的責(zé)任和執(zhí)行命令的責(zé)任分割開,從而使你可用不同的請求對客戶進行參數(shù)化杜漠,對請求排隊或記錄請求日志极景,以及支持可撤銷的操作

命令模式結(jié)構(gòu):

  1. Receiver:命令接收者,真正執(zhí)行命令的對象
  2. Command:執(zhí)行命令的接口驾茴,聲明執(zhí)行命令的方法
  3. ConcreteCommand:實現(xiàn)命令接口的命令對象盼樟,是“虛”的實現(xiàn);通常會持有命令接收者锈至,并調(diào)用命令接收者的功能來完成命令要執(zhí)行的操作
  4. Invoker:調(diào)用命令對象去執(zhí)行命令晨缴,通常會持有命令對象;這是使用命令對象的入口
  5. Client:創(chuàng)建具體的命令對象峡捡,并且設(shè)置命令對象的接收者
// 命令接收者:真正執(zhí)行命令的對象
class Tv {
    public void turnOn() {
        System.out.println("電視機開機");
    }

    public void turnOff() {
        System.out.println("電視機關(guān)機");
    }
}

// 執(zhí)行命令的接口
interface Command {
    void execute();

    void undo();
}

// 開機命令
class OnCommand implements Command {
    Tv tv;

    public OnCommand(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOn();
    }

    @Override
    public void undo() {
        tv.turnOff();
    }
}

// 關(guān)機命令
class OffCommand implements Command {
    Tv tv;

    public OffCommand(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.turnOff();
    }

    @Override
    public void undo() {
        tv.turnOn();
    }
}

// 空命令:可以用來初始化Invoker中的每個命令
class EmptyCommand implements Command {
    @Override
    public void execute() {
    }

    @Override
    public void undo() {
    }
}

// 遙控器
class Invoker {
    Command onCommand = new EmptyCommand();
    Command offCommand = new EmptyCommand();

    public Invoker(Command onCommand, Command offCommand) {
        this.onCommand = onCommand;
        this.offCommand = offCommand;
    }

    public void turnOn() {
        onCommand.execute();
    }

    public void turnOff() {
        offCommand.execute();
    }
}

public class CommandClient {
    public static void main(String[] args) {
        Tv tv = new Tv();
        Invoker invoker = new Invoker(new OnCommand(tv), new OffCommand(tv));
        invoker.turnOn();
        invoker.turnOff();
    }
}

3. 訪問者模式

訪問者模式:把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作解耦合击碗,使得可以在不改變各元素的類的前提下定義作用于這些元素的新操作

訪問者模式適用于數(shù)據(jù)結(jié)構(gòu)相對穩(wěn)定、算法又易變化的系統(tǒng)们拙,因為訪問者模式使得算法操作增加變得容易

結(jié)構(gòu)對象是使用訪問者模式必備條件稍途,而且這個結(jié)構(gòu)對象必須存在遍歷自身各個對象的方法。這便類似于Java語言當(dāng)中的collection概念了

訪問者模式涉及的角色:

  1. Visitor:抽象訪問者角色砚婆,為該對象結(jié)構(gòu)中的每一個具體元素角色聲明一個訪問操作接口
  2. ConcreteVisitor:具體訪問者角色械拍,實現(xiàn)Visitor聲明的接口
  3. Element:定義一個接受訪問的操作(accept()),它以一個訪問者(Visitor)作為參數(shù)
  4. ConcreteElement:具體元素装盯,實現(xiàn)了抽象元素(Element)所定義的接受操作接口
  5. ObjectStructure:結(jié)構(gòu)對象角色殊者,這是使用訪問者模式必備的角色。它具備以下特性:能枚舉它的元素验夯;可以提供一個高層接口以允許訪問者訪問它的元素

據(jù)《大話設(shè)計模式》中說猖吴,訪問者模式算是最復(fù)雜也是最難以理解的一種模式了!

import java.util.ArrayList;
import java.util.List;

// 抽象訪問者角色
interface Visitor {
    void visitElementA(ConcreteElementA elementA);

    void visitElementB(ConcreteElementB elementB);
}

/**
 * 具體訪問者角色:1
 * 不同的具體訪問者挥转,訪問元素的方式可能不同
 */
class ConcreteVisitor1 implements Visitor {
    @Override
    public void visitElementA(ConcreteElementA elementA) {
        System.out.println("以方式1來訪問元素A");
    }

    @Override
    public void visitElementB(ConcreteElementB elementB) {
        System.out.println("以方式1來訪問元素B");
    }
}

// 具體訪問者角色:2
class ConcreteVisitor2 implements Visitor {
    @Override
    public void visitElementA(ConcreteElementA elementA) {
        System.out.println("以方式2來訪問元素A");
    }

    @Override
    public void visitElementB(ConcreteElementB elementB) {
        System.out.println("以方式2來訪問元素B");
    }
}

// 定義一個接受訪問的操作
interface Element {
    void accept(Visitor visitor);
}

/**
 * 具體元素:A
 * 使用了雙分派:
 * 第一次分派:在客戶端調(diào)用時將具體狀態(tài)作為參數(shù)傳遞到ConcreteElementA中
 * 第二次分派:將ConcreteElementA對象本身作為參數(shù)傳遞到visitElementA中
 */
class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitElementA(this);
    }
}

// 具體元素:B
class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitElementB(this);
    }
}

// 結(jié)構(gòu)對象角色
class ObjectStructure {
    List<Element> elementList = new ArrayList<>();

    public void attach(Element element) {
        elementList.add(element);
    }

    public void detach(Element element) {
        elementList.remove(element);
    }

    public void display(Visitor visitor) {
        for (Element element : elementList) {
            element.accept(visitor);
        }
    }
}

public class VisitorClient {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.attach(new ConcreteElementA());
        objectStructure.attach(new ConcreteElementB());
        objectStructure.attach(new ConcreteElementA());
        objectStructure.display(new ConcreteVisitor1());
        System.out.println("----------------------");
        objectStructure.display(new ConcreteVisitor2());
    }
}

4. 迭代器模式

迭代器模式:提供一種方法順序訪問一個聚合對象中的各個元素海蔽,而又不需要暴露該對象的內(nèi)部表示

迭代器模式涉及的角色:

  1. Iterator(迭代器):定義訪問和遍歷元素的接口
  2. ConcreteIterator(具體迭代器):實現(xiàn)迭代器接口;對該聚合遍歷時跟蹤當(dāng)前位置
  3. Aggregate(聚合):定義創(chuàng)建相應(yīng)迭代器對象的接口
  4. ConcreteAggregate(具體聚合):實現(xiàn)創(chuàng)建相應(yīng)迭代器的接口绑谣,該操作返回ConcreteIterator的一個適當(dāng)?shù)膶嵗?/li>
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

// 迭代器接口使用java現(xiàn)成的java.util.Iterator接口
// 具體迭代器
class ListIterator<E> implements Iterator<E> {
    List<E> list;
    // 要返回的下一個元素的索引
    int cursor = 0;
    // 返回的最后一個元素的索引
    int lastRet = -1;

    public ListIterator(List<E> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return cursor < list.size();
    }

    @Override
    public E next() {
        if (cursor >= list.size())
            throw new NoSuchElementException();
        lastRet = cursor;
        cursor++;
        return list.get(lastRet);
    }

    @Override
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        list.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
    }
}

// 聚合
interface MyCollection {
    Iterator<String> getIterator();

    void addString(String s);
}

// 具體聚合
class MyList implements MyCollection {
    List<String> list = new ArrayList<>();

    @Override
    public ListIterator<String> getIterator() {
        return new ListIterator<>(list);
    }

    @Override
    public void addString(String s) {
        list.add(s);
    }
}

public class IteratorClient {
    public static void main(String[] args) {
        MyList myList = new MyList();
        myList.addString("1");
        myList.addString("2");
        myList.addString("3");
        ListIterator<String> listIterator = myList.getIterator();
        // 1 3
        while (listIterator.hasNext()) {
            String next = listIterator.next();
            if (next.equals("2"))
                listIterator.remove();
            else
                System.out.print(next + " ");
        }
    }
}

5. 觀察者模式*

觀察者模式:定義對象間一對多的依賴關(guān)系党窜,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新借宵。在觀察者模式中幌衣,主體是通知的發(fā)布者,它發(fā)出通知時并不需要知道誰是它的觀察者,可以有任意數(shù)目的觀察者訂閱并接收通知

觀察者模式涉及的角色:

  1. 抽象觀察者(Observer):為所有的具體觀察者定義一個接口豁护,在得到主題通知時更新自己
  2. 具體觀察者(Concrete Observer):實現(xiàn)抽象觀察者角色所要求的更新接口哼凯,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調(diào)
  3. 抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數(shù)量的觀察者楚里。抽象主題提供一個接口断部,可以增加和刪除觀察者對象
  4. 具體主題(Concrete Subject):將有關(guān)狀態(tài)存入具體觀察者對象;在具體主題內(nèi)部狀態(tài)改變時班缎,給所有登記過的觀察者發(fā)出通知

java.util.Observable類就使用了觀察者模式

發(fā)布訂閱機制就類似于觀察者模式

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

// 需要更新的數(shù)據(jù)
@Data
@NoArgsConstructor
@AllArgsConstructor
class UpdatedData {
    String username;
    String password;
}

// 抽象觀察者
interface Observer {
    void update(UpdatedData updatedData);
}

// 具體觀察者:可以有多個
class ConcreteObserver implements Observer {
    UpdatedData updatedData = new UpdatedData();

    @Override
    public void update(UpdatedData updatedData) {
        this.updatedData = updatedData;
        System.out.println(this.toString() + "已更新:" + this.updatedData);
    }
}

// 抽象主題
interface Subject {
    void subscribe(Observer observer);

    void unsubscribe(Observer observer);

    void publish(UpdatedData updatedData);
}

// 具體主題:一般有1個
class ConcreteSubject implements Subject {
    List<Observer> observerList = new ArrayList<>();

    @Override
    public void subscribe(Observer observer) {
        System.out.println(observer + "訂閱");
        observerList.add(observer);
    }

    @Override
    public void unsubscribe(Observer observer) {
        System.out.println(observer + "退訂");
        if (observerList.contains(observer))
            observerList.remove(observer);
    }

    @Override
    public void publish(UpdatedData updatedData) {
        System.out.println("發(fā)布");
        for (Observer observer : observerList) {
            observer.update(updatedData);
        }
    }
}

public class ObserverClient {
    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        Observer observer = new ConcreteObserver();
        subject.subscribe(observer);
        subject.publish(new UpdatedData("root", "123456"));
        subject.unsubscribe(observer);
    }
}

6. 中介者模式

中介者模式(調(diào)停者模式):用一個中介對象來封裝一系列的對象交互蝴光。中介者使各對象不需要顯式地相互引用,從而使其耦合松散达址,而且可以獨立地改變它們之間的交互

中介者模式涉及的角色:

  1. 同事(Colleague):每一個同事都知道它的中介者對象蔑祟,在需要與其他同事通信的時候,與它的中介者通信
  2. 具體同事(ConcreteColleague):實現(xiàn)同事接口
  3. 中介者(Mediator):中介者定義一個接口用于與各同事(Colleague)對象通信
  4. 具體中介者(ConcreteMediator):具體中介者通過協(xié)調(diào)各同事對象實現(xiàn)協(xié)作行為沉唠,了解并維護它的各個同事
import java.util.ArrayList;
import java.util.List;

// 同事
abstract class Colleague {
    Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    abstract void receive();

    abstract void send();
}

// 具體同事:1
class ConcreteColleague1 extends Colleague {
    @Override
    void receive() {
        System.out.println("具體同事1收到請求");
    }

    @Override
    void send() {
        System.out.println("具體同事1發(fā)出請求");
        // 請中介者轉(zhuǎn)發(fā)
        mediator.relay(this);
    }
}

// 具體同事:2
class ConcreteColleague2 extends Colleague {
    @Override
    void receive() {
        System.out.println("具體同事2收到請求");
    }

    @Override
    void send() {
        System.out.println("具體同事2發(fā)出請求");
        // 請中介者轉(zhuǎn)發(fā)
        mediator.relay(this);
    }
}

// 中介者
interface Mediator {
    void register(Colleague colleague);

    void relay(Colleague colleague);
}

// 具體中介者
class ConcreteMediator implements Mediator {
    List<Colleague> colleagueList = new ArrayList<>();

    @Override
    public void register(Colleague colleague) {
        if (!colleagueList.contains(colleague)) {
            colleagueList.add(colleague);
            colleague.setMediator(this);
        }
    }

    @Override
    public void relay(Colleague colleague) {
        // 給除了colleague的所有Colleague轉(zhuǎn)發(fā)
        for (Colleague coll : colleagueList) {
            if (!coll.equals(colleague)) {
                coll.receive();
            }
        }
    }
}

public class MediatorClient {
    public static void main(String[] args) {
        Mediator mediator = new ConcreteMediator();
        Colleague colleague1 = new ConcreteColleague1();
        Colleague colleague2 = new ConcreteColleague2();
        mediator.register(colleague1);
        mediator.register(colleague2);
        colleague1.send();
        System.out.println("---------------------");
        colleague2.send();
    }
}

7. 備忘錄模式

備忘錄模式又叫做快照模式或Token模式:在不破壞封裝性的前提下疆虚,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài)右冻。這樣以后就可將該對象恢復(fù)到原先保存的狀態(tài)

備忘錄模式涉及的角色:

  1. Originator(發(fā)起人):負責(zé)創(chuàng)建一個備忘錄Memento装蓬,用以記錄當(dāng)前時刻自身的內(nèi)部狀態(tài)著拭,并可使用備忘錄恢復(fù)內(nèi)部狀態(tài)纱扭。Originator可以根據(jù)需要決定Memento存儲自己的哪些內(nèi)部狀態(tài)。
  2. Memento(備忘錄):負責(zé)存儲Originator對象的內(nèi)部狀態(tài)儡遮,并可以防止Originator以外的其他對象訪問備忘錄乳蛾。備忘錄有兩個接口:Caretaker只能看到備忘錄的窄接口,他只能將備忘錄傳遞給其他對象鄙币。Originator卻可看到備忘錄的寬接口肃叶,允許它訪問返回到先前狀態(tài)所需要的所有數(shù)據(jù)。
  3. Caretaker(管理者):負責(zé)備忘錄Memento十嘿,不能對Memento的內(nèi)容進行訪問或者操作因惭。
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

// 發(fā)起人
@Data
class Originator {
    String state;

    public void setStateFromMemento(Memento memento) {
        state = memento.getState();
    }

    public Memento createMementoToSaveState() {
        return new Memento(state);
    }
}

// 備忘錄
class Memento {
    String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// 管理者
class Caretaker {
    List<Memento> mementoList = new ArrayList<>();

    void add(Memento memento) {
        mementoList.add(memento);
    }

    Memento get(int index) {
        return mementoList.get(index);
    }
}

public class MementoClient {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Originator originator = new Originator();
        originator.state = "狀態(tài)0";
        caretaker.add(originator.createMementoToSaveState());
        originator.state = "狀態(tài)1";
        caretaker.add(originator.createMementoToSaveState());
        // 當(dāng)前狀態(tài):Originator(state=狀態(tài)1)
        System.out.println("當(dāng)前狀態(tài):" + originator);
        originator.setStateFromMemento(caretaker.get(0));
        // 恢復(fù)后,當(dāng)前狀態(tài):Originator(state=狀態(tài)0)
        System.out.println("恢復(fù)后绩衷,當(dāng)前狀態(tài):" + originator);
    }
}

8. 解釋器模式

解釋器模式:給定一個語言蹦魔,定義它的文法的一種表示,并定義一個解釋器咳燕,這個解釋器使用該表示來解釋語言中的句子勿决。

解釋器模式涉及的角色:

  1. 上下文(Context):包含解釋器之外的一些全局信息
  2. 抽象表達式(AbstractExpression):聲明一個抽象的解釋操作,這個接口為抽象語法樹中所有的結(jié)點所共享招盲。
  3. 終結(jié)符表達式(TerminalExpression):實現(xiàn)與文法中的終結(jié)符相關(guān)聯(lián)的解釋操作
  4. 非終結(jié)符表達式(NonterminalExpression):為文法中的非終結(jié)符實現(xiàn)解釋操作低缩;解釋一般要遞歸地調(diào)用解釋操作(Interpret)
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 * 抽象表達式
 * Map<String, Integer> context充當(dāng)上下文
 */
interface AbstractExpression {
    // Map中的key為變量名,value為變量值
    int interpret(Map<String, Integer> context);
}

// 終結(jié)符表達式
class TerminalExpression implements AbstractExpression {
    String key;

    public TerminalExpression(String key) {
        this.key = key;
    }

    // 根據(jù)變量名曹货,然后對應(yīng)的值
    @Override
    public int interpret(Map<String, Integer> context) {
        return context.get(this.key);
    }
}

/**
 * 非終結(jié)符表達式:
 * 每個運算符只和其左右兩邊的數(shù)字有關(guān)咆繁,
 * 但左右兩邊的數(shù)字也可能是一個解析結(jié)果讳推,
 * 而且無論哪個解析結(jié)果,都是AbstractExpression類型
 */
abstract class NonterminalExpression implements AbstractExpression {
    AbstractExpression left;
    AbstractExpression right;

    public NonterminalExpression(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }
}

// 加運算符
class AddOperator extends NonterminalExpression {
    public AddOperator(AbstractExpression left, AbstractExpression right) {
        super(left, right);
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return super.left.interpret(context) + super.right.interpret(context);
    }
}

// 減運算符
class SubOperator extends NonterminalExpression {
    public SubOperator(AbstractExpression left, AbstractExpression right) {
        super(left, right);
    }

    @Override
    public int interpret(Map<String, Integer> context) {
        return super.left.interpret(context) - super.right.interpret(context);
    }
}

public class InterpreterClient {
    public static void main(String[] args) {
        System.out.println("定義變量:");
        Map<String, Integer> context = new HashMap<>();
        context.put("a", 10);
        context.put("b", 5);
        context.put("c", 6);
        context.entrySet().forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));
        System.out.println("計算表達式:");
        String expr = "a + b - c";
        System.out.println(expr + " = " + calc(expr).interpret(context));
    }

    // 計算的規(guī)則
    public static AbstractExpression calc(String expr) {
        LinkedList<AbstractExpression> stack = new LinkedList<>();
        AbstractExpression left, right;
        for (int i = 0; i < expr.length(); i++) {
            switch (expr.charAt(i)) {
                case '+':
                    left = stack.pop();
                    right = new TerminalExpression(expr.charAt(++i) + "");
                    stack.push(new AddOperator(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    right = new TerminalExpression(expr.charAt(++i) + "");
                    stack.push(new SubOperator(left, right));
                    break;
                case ' ':
                    break;
                default:
                    stack.push(new TerminalExpression(expr.charAt(i) + ""));
                    break;
            }
        }
        return stack.pop();
    }
}

9. 狀態(tài)模式

狀態(tài)模式:允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為

狀態(tài)模式主要解決的是當(dāng)控制一個對象狀態(tài)的條件表達式過于復(fù)雜時的情況么介。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類中娜遵,可以把復(fù)雜的判斷邏輯簡化

狀態(tài)模式涉及的角色:

  1. 環(huán)境(Context):定義客戶感興趣的接口,維護一個ConcreteState子類的實例壤短,這個實例定義當(dāng)前狀態(tài)
  2. 狀態(tài)(State):定義一個接口以封裝與Context的一個特定狀態(tài)相關(guān)的行為
  3. 具體狀態(tài)子類(ConcreteState):每一子類實現(xiàn)一個與Context的一個狀態(tài)相關(guān)的行為

使用狀態(tài)模式前设拟,可以先畫出狀態(tài)轉(zhuǎn)換圖來分析各個狀態(tài)間的關(guān)系

// 環(huán)境
class Context {
    State state;

    public Context(State state) {
        this.state = state;
    }

    void request() {
        state.handle(this);
    }
}

// 狀態(tài)
interface State {
    void handle(Context context);
}

// 具體狀態(tài)子類:A
class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        context.state = new ConcreteStateB();
        System.out.println("已從狀態(tài)A切換到狀態(tài)B");
    }
}

// 具體狀態(tài)子類:B
class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        context.state = new ConcreteStateA();
        System.out.println("已從狀態(tài)B切換到狀態(tài)A");
    }
}

public class StateClient {
    public static void main(String[] args) {
        // 初始化狀態(tài)為A
        Context context = new Context(new ConcreteStateA());
        context.request();
        context.request();
        context.request();
    }
}

10. 策略模式

策略模式:定義一系列的算法,把它們一個個封裝起來久脯,并且使它們可相互替換纳胧;策略模式使得算法可獨立于使用它的客戶而變化

策略模式涉及的角色:

  1. 策略(Strategy):定義所有支持的算法的公共接口;Context使用這個接口來調(diào)用某ConcreteStrategy
  2. 具體策略(ConcreteStrategy):實現(xiàn)Strategy接口的某個算法
  3. 上下文(Context):維護一個對Strategy對象的引用

java.util.Arrays就使用了策略模式:對自定義對象排序時帘撰,根據(jù)不同的排序策略來進行排序

// 策略
interface Strategy {
    void AlgorithmInterface();
}

// 具體策略A
class ConcreteStrategyA implements Strategy {
    @Override
    public void AlgorithmInterface() {
        System.out.println("正在使用策略A");
    }
}

// 具體策略B
class ConcreteStrategyB implements Strategy {
    @Override
    public void AlgorithmInterface() {
        System.out.println("正在使用策略B");
    }
}

// 上下文
class Context {
    Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void contextInterface() {
        this.strategy.AlgorithmInterface();
    }
}

public class StrategyClient {
    public static void main(String[] args) {
        // 默認使用策略A
        Context context = new Context(new ConcreteStrategyA());
        context.contextInterface();
        context.setStrategy(new ConcreteStrategyB());
        context.contextInterface();
    }
}

11. 責(zé)任鏈模式*

責(zé)任鏈模式:由每一個對象對其下家的引用而連接起來形成一條鏈跑慕,請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求摧找。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求核行,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責(zé)任

責(zé)任鏈模式涉及的角色:

  1. 抽象處理者角色(Handler):定義一個處理請求的接口,可以定義出一個方法以設(shè)定和返回對下家的引用
  2. 具體處理者角色(ConcreteHandler):接到請求后蹬耘,如果可處理該請求芝雪,就處理之;否則將該請求轉(zhuǎn)發(fā)給它的后繼者
// 抽象處理者角色
abstract class Handler {
    protected int maxPriority;
    protected Handler successor;

    public Handler setSuccessor(Handler successor) {
        this.successor = successor;
        return this;
    }

    public final void request(int priority) {
        if (priority <= this.maxPriority) {
            handleRequest();
        } else if (successor != null) {
            successor.request(priority);
        } else {
            System.out.println("無法處理");
        }
    }

    abstract void handleRequest();
}

// 具體處理者角色:1
class ConcreteHandler1 extends Handler {
    public ConcreteHandler1(int maxPriority) {
        this.maxPriority = maxPriority;
    }

    @Override
    void handleRequest() {
        System.out.println("第一層處理");
    }
}

// 具體處理者角色:2
class ConcreteHandler2 extends Handler {
    public ConcreteHandler2(int maxPriority) {
        this.maxPriority = maxPriority;
    }

    @Override
    void handleRequest() {
        System.out.println("第二層處理");
    }
}

public class ChainOfResponsibilityClient {
    public static void main(String[] args) {
        // 所有請求综苔,都從第一個Handler開始處理
        Handler handler = new ConcreteHandler1(10).setSuccessor(
                new ConcreteHandler2(100).setSuccessor(
                        null));
        handler.request(5);
        System.out.println("---------");
        handler.request(50);
        System.out.println("---------");
        handler.request(500);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惩系,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子如筛,更是在濱河造成了極大的恐慌堡牡,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杨刨,死亡現(xiàn)場離奇詭異晤柄,居然都是意外死亡,警方通過查閱死者的電腦和手機妖胀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門芥颈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人做粤,你說我怎么就攤上這事浇借。” “怎么了怕品?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵妇垢,是天一觀的道長。 經(jīng)常有香客問我,道長闯估,這世上最難降的妖魔是什么灼舍? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮涨薪,結(jié)果婚禮上骑素,老公的妹妹穿的比我還像新娘。我一直安慰自己刚夺,他們只是感情好献丑,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著侠姑,像睡著了一般创橄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莽红,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天妥畏,我揣著相機與錄音,去河邊找鬼安吁。 笑死醉蚁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鬼店。 我是一名探鬼主播网棍,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼薪韩!你這毒婦竟也來了确沸?” 一聲冷哼從身側(cè)響起捌锭,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤俘陷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后观谦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拉盾,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年豁状,在試婚紗的時候發(fā)現(xiàn)自己被綠了捉偏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡泻红,死狀恐怖夭禽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谊路,我是刑警寧澤讹躯,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響潮梯,放射性物質(zhì)發(fā)生泄漏骗灶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一秉馏、第九天 我趴在偏房一處隱蔽的房頂上張望耙旦。 院中可真熱鬧,春花似錦萝究、人聲如沸免都。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽琴昆。三九已至,卻和暖如春馆揉,著一層夾襖步出監(jiān)牢的瞬間业舍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工升酣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舷暮,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓噩茄,卻偏偏與公主長得像下面,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绩聘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容