设计模式--简化解释(三)——行为型模式

1.建立型设计模式
2.结构型设计模式
3.行为型设计模式java

行为型设计模式

简而言之android

行为型设计模式关心的是对象之间的责任分配。它们与结构模式的不一样之处在于,它们不只指定告终构,并且还概述了它们之间消息传递/通讯的模式。换句话说,他们帮助回答“在软件组件中如何管理一个行为?”

维基百科说ios

在软件工程中,行为设计模式是一种设计模式,用于识别对象之间的公共通讯模式并实现这些模式. 这样作,这些设计模式在传递信息的时候增长了灵活性。

? 职责链模式

显示举例算法

例如,在你的帐户中有三种支付方式( A, B, C),每个都有不一样的金额的钱。 A中有100美圆, B中有300美圆, C中有1000美圆。选择支付方式的偏好为 A, BC.你尝试购买价值210美圆的商品。使用职责链,首先检查 A可否支持购买,若是能够则进行购买,职责终端。不然,请求转发到帐户 B,若是职责中断,则请求一致转发直到找到符合条件的处理器。在这里, A, B, C是链式链接,整个现象就是职责链。

简而言之编程

职责链模式帮助构建一个对象链。请求从一个端点进入,一直从一个对象到另外一个对象,直到找到合适的处理器。

维基百科说segmentfault

在面向对象的设计中,责任链模式是由一个命令对象的源和一系列处理对象组成的设计模式。 每一个处理对象都包含定义它能够处理的命令对象类型的逻辑;其他的被传递给链中的下一个处理对象。

编程示例设计模式

翻译咱们上面的账户示例。首先,咱们有一个基本账户,它有把账户合并在一块儿的逻辑,和一些其余账户。服务器

public abstract class Account {
    protected float balance;
    private Account successor;

    public Account(float balance) {
        this.balance = balance;
    }

    public void setNext(Account account)
    {
        this.successor = account;
    }

    public void pay(float amount)
    {
        if(canPay(amount))
        {
            System.out.println(String.format("Can pay $%s use %s",amount,this.getClass().getSimpleName()));
        }
        else
        {
            System.out.println(String.format("Can not pay,forwarding:%s",successor.getClass().getSimpleName()));
            successor.pay(amount);
        }
    }

    public boolean canPay(float amount)
    {
        return Float.compare(balance,amount) > 0;
    }
}
public class Bank extends Account {
    public Bank(float balance) {
        super(balance);
    }
}
public class Paypal extends Account {
    public Paypal(float balance) {
        super(balance);
    }
}
public class Bitcoin extends Account{
    public Bitcoin(float balance) {
        super(balance);
    }
}

如今咱们使用上边准备的链式链接。网络

// 咱们准备的支付链以下
//      bank->paypal->bitcoin
//
// 首选bank
//  若是 bank不能支付选择 paypal
//  若是 paypal不能支付选择 bit coin

Account bank = new Bank(100);
Account paypay = new Paypal(200);
Account bitcon = new Bitcoin(300);

bank.setNext(paypay);
paypay.setNext(bitcon);

bank.pay(259);

? 命令模式

现实举例app

一个典型的例子就是你在餐馆点餐。你(“客户端”)问服务员(调用者,“Invoker”)带一些食物(“命令”,Command),服务员简单地将请求转发给厨师,这个厨师是懂得如何烹饪的人。
另外一个例子是你(客户端,"Client")使用遥控(调用者,"Invoke")切换电视节目(命令,"Command")。
简而言之
容许您封装对象中的操做。此模式背后的关键思想是提供将客户端与接收方解耦合的方法。

维基百科说

在面向对象的编程中,命令模式是一种行为设计模式,在该模式中,对象被用来封装执行某个动做所需的全部信息,或者在稍后的时间触发事件。该信息包括方法名称、拥有方法参数的对象以及方法参数的值。

编程示例

首先,咱们有一个接收器,它能够执行全部能够执行的动做。

// Receiver(接收者)
public class Bulb {
    public void turnOn()
    {
        System.out.println("Bulb has been lit");
    }

    public void turnOff()
    {
        System.out.println("Darkness");
    }
}

而后咱们有一个接口,每一个命令都要实现,另外咱们有一组命令。

public interface Command {
    void undo();
    void redo();
    void execute();
}
// Command
public class TurnOffCommand implements Command {
    private Bulb bulb;

    public TurnOffCommand(Bulb bulb) {
        this.bulb = bulb;
    }

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

    @Override
    public void redo() {
        this.bulb.turnOff();
    }

    @Override
    public void execute() {
        this.bulb.turnOff();
    }
}
public class TurnOnCommand implements Command {
    private Bulb bulb;

    public TurnOnCommand(Bulb bulb) {
        this.bulb = bulb;
    }

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

    @Override
    public void redo() {
        this.bulb.turnOn();
    }

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

接着咱们有调用者(Invoker),客户端可使用调用者来处理任意的命令

// 调用者
public class RemoteControl {
    public void submit(Command command)
    {
        command.execute();
    }
}

最后看一下客户端如何使用

Bulb bulb = new Bulb();

Command turnOnCommand = new TurnOnCommand(bulb);
Command turnOffCommand = new TurnOffCommand(bulb);

RemoteControl remoteControl = new RemoteControl();
remoteControl.submit(turnOnCommand);

remoteControl.submit(turnOnCommand);

命令模式还能够用于实现基于事务的系统。当您执行命令的历史时,您将保持它的历史。若是最终的命令被成功执行,那么全部的好方法都只是遍历历史,并在全部执行的命令上执行“撤消”。

➿ 迭代器模式

现实举例

一台旧的收音机将会是一个很好的迭代器的例子,用户能够从某个频道开始,而后使用下一个或以前的按钮来浏览各个频道。 或者举一个MP3播放器或电视机的例子,你能够按下一个和以前的按钮,经过连续的频道。换句话说,它们都提供一个接口,经过各自的频道、歌曲或广播电台进行迭代。

简而言之

它提供了一种方法来访问对象的元素,而不暴露底层的表示。

维基百科说

在面向对象编程中,迭代器模式是一种设计模式,其中迭代器用于遍历容器并访问容器的元素。 迭代器模式将算法从容器中分离出来;在某些状况下,算法必须是特定于容器的,所以不能解耦。

编程举例

在Java中能够结合Iterator接口来实现迭代器模式。翻译上边收音机的例子以下;

public class RadioStation {
    private float frequency;

    public RadioStation(float frequency) {
        this.frequency = frequency;
    }

    public float getFrequency() {
        return frequency;
    }
}

咱们有咱们本身的迭代器

public class StationList implements Iterator<RadioStation> {

    private List<RadioStation> stations = new ArrayList<>();
    private int counter = 0;

    @Override
    public boolean hasNext() {
        return counter < stations.size();
    }

    @Override
    public RadioStation next() {
        return stations.get(counter++);
    }

    public void add(RadioStation radioStation)
    {
        stations.add(radioStation);
    }

    public RadioStation remove(RadioStation radioStation)
    {
        for(int i = 0; i < stations.size(); i++)
        {
            if(Float.compare(stations.get(i).getFrequency(),radioStation.getFrequency())==0)
            {
                return  stations.remove(i);
            }
        }

        return null;
    }

    public int count()
    {
        return stations.size();
    }

    public RadioStation current()
    {
        return stations.get(counter);
    }

    public int key()
    {
        return counter;
    }

    public void rewind()
    {
        counter=0;
    }

}

使用方式以下

StationList stationList = new StationList();
stationList.add(new RadioStation(120.1F));
stationList.add(new RadioStation(99.1F));
stationList.add(new RadioStation(156.7F));
stationList.add(new RadioStation(138.2F));
stationList.add(new RadioStation(89.6F));
stationList.add(new RadioStation(78.9F));

while(stationList.hasNext())
{
    System.out.println(stationList.next().getFrequency());
}

? 中介模式

现实举例

一个普通的例子是当你和某人在你的移动电话上交谈时,你和他们之间有一个网络供应商,你的谈话经过它而不是直接发送。在这种状况下,网络供应商是中介。

简而言之

中介模式添加第三方对象(称为中介)来控制两个对象之间的交互(称为同事)。它有助于减小相互通讯的类之间的耦合。由于如今他们不须要知道彼此的实现。

维基百科说

在软件工程中,中介模式定义了一个对象,它封装了一组对象如何交互。这种模式被认为是一种行为模式,由于它能够改变程序的运行行为。

编程示例

这里是一个与用户相互发送消息的聊天室最简单的例子。

首先咱们有中介,也就是聊天室。

public interface ChatRoomMediator {
    void showMessage(User user,String message);
}
// Mediator
public class ChatRoom implements ChatRoomMediator {
    private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void showMessage(User user, String message) {
        String date = sf.format(Calendar.getInstance().getTime());
        System.out.println(String.format("%s [%s] says:%s",date,user.getUserName(),message));
    }
}

下面是咱们的用户

public class User {
    private String userName;
    private ChatRoomMediator chatRoomMediator;

    public User(String userName, ChatRoomMediator chatRoomMediator) {
        this.userName = userName;
        this.chatRoomMediator = chatRoomMediator;
    }

    public String getUserName() {
        return userName;
    }

    public void sendMessage(String message)
    {
        this.chatRoomMediator.showMessage(this,message);
    }
}

使用以下

ChatRoomMediator mediator = new ChatRoom();
User john = new User("John",mediator);
User jane = new User("Jane",mediator);

john.sendMessage("Hi there!");
jane.sendMessage("Hey!");

? 备忘录模式

现实举例

以计算器为例,当您执行某些计算时,最后的计算将保存在内存中,这样您就能够返回到它,并使用一些操做按钮(即管理员)恢复它。

简而言之

Memento模式是关于捕获和存储对象的当前状态的方式,它能够在稍后以一种平滑的方式恢复。

维基百科说

memento模式是一种软件设计模式,它提供了将对象恢复到之前状态的能力(经过回滚撤销)。

一般在须要提供某种撤销功能时很是有用。

编程示例

让咱们举一个文本编辑器的例子,它能够随时保存状态,若是须要,能够恢复。

首先,咱们有一个能够保存编辑器状态的memento对象。

public class EditorMemento {
    private String content;

    public EditorMemento(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }
}

界限来咱们有一个编辑器来使用memento对象

public class Editor {
    private String content="";

    public void type(String words)
    {
       content = String.format("%s %s",content,words);
    }

    public EditorMemento save()
    {
        return new EditorMemento(content);
    }

    public void resotre(EditorMemento memento)
    {
        this.content = memento.getContent();
    }

    public String getContent() {
        return content;
    }
}

使用方式以下

Editor editor = new Editor();
editor.type("This is the first sentence.");
editor.type("This is second.");

EditorMemento memento = editor.save();
editor.type("And this is third.");
editor.resotre(memento);

System.out.println(editor.getContent());

? 观察者模式

现实举例

一个很好的例子就是求职者在招聘网站时,只要有匹配的工做机会,他们就会获得通知。

简而言之

定义对象之间的依赖关系,以便每当对象更改其状态时,都会通知全部依赖对象。

维基百科说

观察者模式是一种软件设计模式,其中一个对象被称为主题,它维护一个被称为观察者的依赖项列表,并经过调用其中一个方法来自动通知它们任何状态变化。

编程示例
翻译咱们上边的例子。首先咱们有须要被通知招聘职位的求职者。

注:JDK中提供了Observer接口和Observal抽象类来实现观察者模式
public class JobPost {
    public String title;

    public JobPost(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
}
public class JobSeeker implements Observer {
    private String name;

    public JobSeeker(String name) {
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        JobPost jobPost = (JobPost)arg;

        System.out.println(String.format("Hi,%s!New Job posted:%s",name,jobPost.getTitle()));
    }
}

而后,咱们会有招聘人员会订阅的招聘信息。

public class JobPostings extends java.util.Observable {

    private void notity(JobPost jobPost)
    {
        super.setChanged();
        notifyObservers(jobPost);
    }

    public void addJob(JobPost jobPost)
    {
        notity(jobPost);
    }
}

使用方式以下

JobSeeker john = new JobSeeker("John");
JobSeeker jane = new JobSeeker("Jane");

JobPostings jobPostings = new JobPostings();
jobPostings.addObserver(john);
jobPostings.addObserver(jane);

jobPostings.addJob(new JobPost("Java Developer"));

? 访问者模式

现实举例

考虑某人去迪拜。 他们只是须要一种方式(即签证)进入迪拜。抵达后,他们能够自行前往迪拜的任何地方,而无需事先征得许可或作一些跑腿的工做,以便参观任何地方,只要让他们知道一个地方,他们就能够去参观。 访问者模式容许你这样作,它能够帮助你添加访问的地方,这样他们就能够尽量多地访问,而没必要作任何跑腿的工做。

简而言之

访问者模式容许您在不修改对象的状况下为对象添加更多操做。

维基百科说

在面向对象编程和软件工程中,访问者设计模式是一种将算法从其操做的对象结构中分离出来的方法。这种分离的实际结果是,在不修改这些结构的状况下,能够向现有的对象结构添加新的操做。这是遵循开放/封闭原则的一种方法。

编程示例

让咱们举一个动物园模拟的例子,咱们有几种不一样种类的动物,咱们必须让它们发声。 咱们使用访问者模式来翻译一下这个例子。

// Visitee
public interface Animal {
    void accept(AnimalOperation operation);
}

// Visitor
public interface AnimalOperation {
    void visitMonkey(Monkey monkey);
    void visitLoin(Lion lion);
    void visitDolphin(Dolphin dolphin);
}

动物的实现

public class Monkey implements Animal {
    public void shout()
    {
        System.out.println("Ooh oo aa aa!");
    }

    @Override
    public void accept(AnimalOperation operation) {
        operation.visitMonkey(this);
    }
}
public class Dolphin implements Animal {
    public void speak()
    {
        System.out.println("Tuut tuttu tuutt!");
    }

    @Override
    public void accept(AnimalOperation operation) {
        operation.visitDolphin(this);
    }
}
public class Lion implements Animal {
    public void roar()
    {
        System.out.println("Roaaar");
    }

    @Override
    public void accept(AnimalOperation operation) {
        operation.visitLoin(this);
    }
}

访问者

public class Speak implements AnimalOperation {
    @Override
    public void visitMonkey(Monkey monkey) {
        monkey.shout();
    }

    @Override
    public void visitLoin(Lion lion) {
        lion.roar();
    }

    @Override
    public void visitDolphin(Dolphin dolphin) {
        dolphin.speak();
    }
}

使用方式以下

Monkey monkey = new Monkey();
        Lion lion = new Lion();
        Dolphin dolphin = new Dolphin();

        Speak speak = new Speak();

        monkey.accept(speak);
        lion.accept(speak);
        dolphin.accept(speak);

咱们本能够简单地为动物创建一个继承等级,但若是咱们须要向动物添加新动做,咱们就必须修改动物。但如今咱们不须要改变它们。例如,假设咱们被要求将跳转行为添加到动物中,咱们能够简单地经过建立一个新的访问者来添加该行为。

public class Jump implements AnimalOperation {
    @Override
    public void visitMonkey(Monkey monkey) {
        System.out.println("Jumped 20 feet high! on to the tree!");
    }

    @Override
    public void visitLoin(Lion lion) {
        System.out.println("Jumped 7 feet! Back on the ground!");
    }

    @Override
    public void visitDolphin(Dolphin dolphin) {
        System.out.println("Walked on water a little and disappeared");
    }
}

使用以下

Monkey monkey = new Monkey();
Lion lion = new Lion();
Dolphin dolphin = new Dolphin();

Speak speak = new Speak();

monkey.accept(speak);
lion.accept(speak);
dolphin.accept(speak);
System.out.println("=======================");

AnimalOperation jump = new Jump();
monkey.accept(jump);
lion.accept(jump);
dolphin.accept(jump);

? 策略模式

现实举例

考虑一下排序的例子,咱们实现了冒泡排序,但数据开始增加,而冒泡排序开始变得很是缓慢。为了解决这个问题,咱们实现了快速排序。可是如今,尽管快速排序算法在大型数据集上作得更好,可是对于较小的数据集来讲,它是很是慢的。为了处理这个问题,咱们实现了一个策略,在这个策略中,小数据集,冒泡排序将被使用,并用于更大的,快速排序。

简而言之

策略模式容许您根据状况切换算法或策略。策略模式容许您根据状况切换算法或策略。

维基百科说

在计算机编程中,策略模式(也称为策略模式)是一种行为软件设计模式,它容许在运行时选择算法的行为。

编程示例

翻译咱们上面的例子。首先,咱们有策略接口和不一样的策略实现。

public interface SortStrategy {
    int[] sort(int[] arr);
}
public class BubbleSortStrategy implements SortStrategy {
    @Override
    public int[] sort(int[] arr) {
        System.out.println("Sorting using bubble sort");

        return arr;
    }
}
public class QuickSortStrategy implements SortStrategy{
    @Override
    public int[] sort(int[] arr) {
        System.out.println("Sorting using quick sort");
        return arr;
    }
}

咱们的客户端可使用任何策略。

public class Sorter {
    private SortStrategy sortStrategy;

    public Sorter(SortStrategy sortStrategy) {
        this.sortStrategy = sortStrategy;
    }

    public int[] sort(int[] arr)
    {
        return sortStrategy.sort(arr);
    }
}

使用方式以下

int[] arr = {1, 5, 4, 3, 2, 8};

Sorter sorter = new Sorter(new BubbleSortStrategy());
sorter.sort(arr);
System.out.println("=========================");
sorter = new Sorter(new QuickSortStrategy());
sorter.sort(arr);

? 状态模式

现实举例

假设您正在使用一些绘图应用程序,您选择画笔绘制。如今画笔会根据所选的颜色改变它的行为若是你选择了红色,它会画出红色,若是蓝色,它会是蓝色的等等。

简而言之

它容许在状态更改时更改类的行为。

维基百科说

状态模式是一种行为软件设计模式,它以面向对象的方式实现状态机。 在状态模式下,状态机经过实现每一个单个状态做为状态模式接口的派生类实现,并经过调用模式父类定义的方法实现状态转换。
状态模式能够解释为一种策略模式,它能够经过在模式接口中定义的方法调用来切换当前策略。

编程示例

让咱们举一个文本编辑器的例子,它容许你改变输入的文本的状态,若是你选择了粗体,它开始以粗体输入;若是选择斜体,以斜体输入,等等。

首先咱们有状态接口和状态的实现。

public interface WriteState {
    void write(String word);
}
public class UpperState implements WriteState {
    @Override
    public void write(String word) {
        System.out.println(word.toUpperCase());
    }
}
public class LowerState implements WriteState {
    @Override
    public void write(String word) {
        System.out.println(word.toLowerCase());
    }
}
public class DefaultState implements WriteState {
    @Override
    public void write(String word) {
        System.out.println(word);
    }
}

而后咱们有一个编辑器

public class TextEditor {
    private WriteState writeState;

    public TextEditor(WriteState writeState) {
        this.writeState = writeState;
    }

    public void setWriteState(WriteState writeState) {
        this.writeState = writeState;
    }

    public void type(String word)
    {
        this.writeState.write(word);
    }
}

使用方式以下

TextEditor editor = new TextEditor(new DefaultState());
editor.type("First line");

editor.setWriteState(new LowerState());
editor.type("Second line");
editor.type("Third line");

editor.setWriteState(new UpperState());
editor.type("Forth line");
editor.type("Fifth line");

? 模版方法模式

现实举例

假设咱们要建一些房子。建造的步骤多是这样的。

  • 打地基
  • 建墙
  • 增长房顶
  • 增长其余的楼层

这些步骤的顺序是不可能改变的,例如,在建造墙以前你不能建造屋顶,可是每个步骤均可以被修改,例如墙壁能够用木头或聚酯或石头作。

简而言之

模板方法定义了如何执行某个算法的骨架,但将这些步骤的实现转移到子类中。

维基百科说

在软件工程中,模板方法模式是一种行为设计模式,它在操做中定义算法的程序骨架,将一些步骤推迟到子类。它让一我的从新定义算法的某些步骤而不改变算法的结构。

Programmatic Example

假设咱们有一个构建工具,它能够帮助咱们测试、lint、构建、生成构建报告(好比代码覆盖率报告、linting报告等),并在测试服务器上部署咱们的应用程序。

首先,咱们有一个为构建算法指定骨架的基类。

public abstract class Builder {

    public void build() {
        test();
        lint();
        assemble();
        deploy();
    }

    public abstract void test();

    public abstract void lint();

    public abstract void assemble();

    public abstract void deploy();
}

实现

public class AndroidBuilder extends Builder {
    @Override
    public void test() {
        System.out.println("Running android tests");
    }

    @Override
    public void lint() {
        System.out.println("Linting the android code");
    }

    @Override
    public void assemble() {
        System.out.println("Assembling the android build");
    }

    @Override
    public void deploy() {
        System.out.println("Deploying android build to server");
    }
}
public class IOSBuilder extends Builder {
    @Override
    public void test() {
        System.out.println("Running ios tests");
    }

    @Override
    public void lint() {
        System.out.println("Linting the ios code");
    }

    @Override
    public void assemble() {
        System.out.println("Assembling the ios build");
    }

    @Override
    public void deploy() {
        System.out.println("Deploying ios build to server");
    }
}

使用以下

Builder builder = new AndroidBuilder();
builder.build();
System.out.println("========================");
builder = new IOSBuilder();
builder.build();
相关文章
相关标签/搜索