【整理】设计模式代码示例及应用场景3

行为型模式

责任链模式(Chain of Responsibility)

  • 描述:使多个处理者对象有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
  • 优点:降低耦合度,增强给予请求的类和处理请求的类的灵活性。

JS示例

// 定义抽象处理者
class Handler {
  constructor(successor = null) {
    this.successor = successor;
  }

  setNext(successor) {
    this.successor = successor;
    return successor;
  }

  handle(request) {
    if (this.successor) {
      return this.successor.handle(request);
    }
  }
}

// 定义具体的处理者
class ConcreteHandler1 extends Handler {
  handle(request) {
    if (request >= 0 && request < 10) {
      console.log(`ConcreteHandler1 handled request: ${request}`);
    } else if (this.successor) {
      this.successor.handle(request);
    }
  }
}

class ConcreteHandler2 extends Handler {
  handle(request) {
    if (request >= 10 && request < 20) {
      console.log(`ConcreteHandler2 handled request: ${request}`);
    } else if (this.successor) {
      this.successor.handle(request);
    }
  }
}

// 创建处理者链
const handler1 = new ConcreteHandler1();
const handler2 = new ConcreteHandler2();

handler1.setNext(handler2);

// 发送请求
[8, 15, 25].forEach(request => {
  handler1.handle(request);
});

在这个例子中,我们定义了两个具体的处理者 ConcreteHandler1 和 ConcreteHandler2,它们各自处理特定范围内的请求。请求被发送给 handler1,然后根据请求的值决定是否处理,或者将请求传递给下一个处理者 handler2。

PHP示例

下面是一个 PHP 的责任链模式示例,展示了如何处理用户发布的帖子审核流程,其中包含版主、管理员和治安部门三个级别的处理者。

// 首先,定义一个抽象的处理者类,这个类将包含处理请求的通用逻辑和设置下一个处理者的功能。
interface HandlerInterface {
    public function setNext(HandlerInterface $handler): HandlerInterface;
    public function handle(string $post): string;
}

abstract class AbstractHandler implements HandlerInterface {
    protected $successor;

    public function setNext(HandlerInterface $handler): HandlerInterface {
        $this->successor = $handler;
        return $handler;
    }

    public function handle(string $post): string {
        if ($this->successor) {
            return $this->successor->handle($post);
        }
        return "Post not handled.";
    }
}
// 接下来,定义具体的处理者类,每个类都会覆盖 handle 方法来提供具体的处理逻辑。
class Moderator extends AbstractHandler {
    public function handle(string $post): string {
        if (strpos($post, 'spam') === false) {
            return "Post approved by moderator.";
        }
        return parent::handle($post);
    }
}

class Administrator extends AbstractHandler {
    public function handle(string $post): string {
        if (strpos($post, 'sensitive') === false) {
            return "Post approved by administrator.";
        }
        return parent::handle($post);
    }
}

class LawEnforcement extends AbstractHandler {
    public function handle(string $post): string {
        if (strpos($post, 'illegal') === false) {
            return "Post approved by law enforcement.";
        }
        return "Post rejected due to illegal content.";
    }
}
// 最后,创建处理者链并发送请求:
$moderator = new Moderator();
$administrator = new Administrator();
$lawnEnforcement = new LawEnforcement();

// 构建责任链
$moderator->setNext($administrator)->setNext($lawnEnforcement);

// 测试不同的帖子
$posts = [
    "This is a normal post.",
    "This post contains spam.",
    "This post contains sensitive information.",
    "This post is illegal."
];

foreach ($posts as $post) {
    echo "Handling post: \"$post\"\n";
    echo $moderator->handle($post) . "\n";
}

在这个示例中,Moderator、Administrator 和 LawEnforcement 分别负责检查帖子是否包含垃圾信息、敏感信息和非法内容。如果帖子通过了当前处理者的检查,它会继续传递给链中的下一个处理者。如果帖子包含处理者不能接受的内容,它将停止在当前处理者处并返回相应的拒绝信息。

应用场景

  1. 有多个对象可以处理一个请求,但是具体哪个对象处理该请求在运行时刻自动确定。
  2. 希望避免请求的发送者和接收者之间的耦合,让请求可以自由地在对象之间传递。
  3. 处理一个请求的算法应该可以动态配置。

这个模式的好处是,你可以轻松地添加、删除或重新排列处理者,而无需修改客户端代码。这使得系统更加灵活和可扩展。

命令模式(Command)

  • 描述:将一个请求封装为一个对象,从而使你可用不同的请求把客户端参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
  • 优点:请求发送者与请求接收者解耦,可以实现命令的撤销和重做。

JS示例

下面是一个使用 ES6 的命令模式示例,我们将创建一个简单的文本编辑器,其中包含一些基本的编辑命令,如插入、删除和撤销。

// 首先,定义一个命令接口:
class Command {
  constructor(editor) {
    this.editor = editor;
  }

  execute() {
    throw new Error('Method not implemented.');
  }

  undo() {
    throw new Error('Method not implemented.');
  }
}
// 然后,定义具体的命令类:
class InsertCommand extends Command {
  constructor(editor, text) {
    super(editor);
    this.text = text;
  }

  execute() {
    this.editor.insert(this.text);
    this.previousText = this.editor.getText();
  }

  undo() {
    this.editor.setText(this.previousText);
  }
}

class DeleteCommand extends Command {
  constructor(editor, start, end) {
    super(editor);
    this.start = start;
    this.end = end;
  }

  execute() {
    this.removedText = this.editor.getText().slice(this.start, this.end);
    this.editor.deleteText(this.start, this.end);
  }

  undo() {
    this.editor.insertText(this.start, this.removedText);
  }
}
// 接着,定义接收者(Editor):
class Editor {
  constructor() {
    this.text = '';
  }

  insert(text) {
    this.text += text;
  }

  deleteText(start, end) {
    this.text = this.text.slice(0, start) + this.text.slice(end);
  }

  insertText(position, text) {
    this.text = this.text.slice(0, position) + text + this.text.slice(position);
  }

  getText() {
    return this.text;
  }

  setText(text) {
    this.text = text;
  }
}
// 最后,创建一个调用者(Invoker),它将存储命令并执行它们:
class Invoker {
  constructor() {
    this.commands = [];
    this.current = -1;
  }

  storeAndExecute(command) {
    this.current++;
    if (this.current < this.commands.length) {
      this.commands.splice(this.current);
    }
    this.commands.push(command);
    command.execute();
  }

  undo() {
    if (this.current > -1) {
      this.commands[this.current].undo();
      this.current--;
    }
  }
}
// 现在,我们可以使用这些类来模拟编辑器的行为:
const editor = new Editor();
const invoker = new Invoker();

invoker.storeAndExecute(new InsertCommand(editor, 'Hello, '));
invoker.storeAndExecute(new InsertCommand(editor, 'world!'));
console.log(editor.getText()); // 输出: Hello, world!

invoker.undo();
console.log(editor.getText()); // 输出: Hello,

PHP示例

下面是一个简单的命令模式的 PHP 示例,我们将创建一个遥控器,它可以用来控制不同的电器设备,如灯和风扇,执行开和关的操作。

// 首先,定义命令接口:
interface Command {
    public function execute();
    public function undo();
}
// 接着,定义具体的命令类,这里以灯为例:
class LightOnCommand implements Command {
    private $light;

    public function __construct(Light $light) {
        $this->light = $light;
    }

    public function execute() {
        $this->light->turnOn();
    }

    public function undo() {
        $this->light->turnOff();
    }
}

class LightOffCommand implements Command {
    private $light;

    public function __construct(Light $light) {
        $this->light = $light;
    }

    public function execute() {
        $this->light->turnOff();
    }

    public function undo() {
        $this->light->turnOn();
    }
}
// 然后,定义接收者类,这里是灯:
class Light {
    public function turnOn() {
        echo "Light is on.\n";
    }

    public function turnOff() {
        echo "Light is off.\n";
    }
}
// 最后,创建一个调用者类,它将存储并执行命令:
class RemoteControl {
    private $command;

    public function setCommand(Command $command) {
        $this->command = $command;
    }

    public function pressButton() {
        $this->command->execute();
    }

    public function undo() {
        $this->command->undo();
    }
}
// 现在,我们可以使用这些类来模拟遥控器控制灯的行为:
$light = new Light();
$remote = new RemoteControl();

$lightOn = new LightOnCommand($light);
$lightOff = new LightOffCommand($light);

$remote->setCommand($lightOn);
$remote->pressButton(); // 输出: Light is on.

$remote->setCommand($lightOff);
$remote->pressButton(); // 输出: Lig
  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值