您好我正在寻找选择编程设计模式以适合我当前项目的一些指导。
我几个月来一直试图找到一个很好的项目来开始正确使用模式,而我刚刚开始的一个小项目似乎提供了一个完美的学习平台。
基本上我正在创建一个响应用户命令的Telegram Bot。这不是我遇到问题的部分,它是如何最好地构建我的代码,以便添加新命令是干净和结构良好的。
我不需要任何人为我编写任何代码,但是我可以实现适合的设计模式吗?
这是我目前正在做的puesudo(BTW我正在使用Laravel)代码:
//routes.php
Route::post('inbound', ['uses' => 'inboundController@marshall']);
//inboundController.php
public function marshall($inboundMessage){
//Extract the command from the inbound message eg "start"
$command = extractfromtext($text);
//Get the user id from the person who sent the message
$userID = extractIdfromtext($text);
//Compare the command in a switch statement
switch ($command){
case (start):
return $result = new commandStart($userID)->fire();
break;
case (demo):
return $result = new commandDemo($userID)->fire();
break;
case (another):
return $result = new commandAnother($userID)->fire();
break;
default:
break;
}
}
//Each command has it's own class:
//Class commandStart
public function __construct($userID){
$this->userID = $userID
}
publin fuction fire(){
//send a picture to the userID
}
//Class commandDemo
public function __construct($userID){
$this->userID = $userID
}
publin fuction fire(){
//send a message to the userID
}
//Class commandAnother
public function __construct($userID){
$this->userID = $userID
}
publin fuction fire(){
//send a video to the userID
}
这很好用,但我觉得
我对不同类型的模式的所有名称感到困惑。有人会告诉我,哪一个适合这种情况?我很高兴去研究它以及它是如何实现的,但是我不想在追逐鹅的时候选择一个不合适的,因为我不知道更好!
谢谢。
编辑:在我试图使问题变得通用的时候,我似乎太过迟钝了。我已经在使用Larvel的MVC了。这不是问题我认为 - 我想知道哪种设计模式可以让我轻松,干净地添加更多命令 - 希望不必使用switch语句。
在阅读了一些回复后,我想我已经开始了解该怎么做了。出于兴趣 - 是在实际设计模式下建议的结构还是仅仅是良好的结构化代码?
答案 0 :(得分:2)
除了arkascha之外,我还建议你为命令使用抽象类
abstract class Command {
public function __construct( $params ){
// do some common things with $params
$this->do_command();
}
protected function do_command(){
// empty function which will be overwritten by child classes
}
}
你的孩子班就像
class FooCommand extends Command {
public function __construct( $params ){
parent::__construct( $params );
// do something as well
}
// can be public
public function do_command(){
echo __CLASS__, '::FOO';
}
}
class BarCommand extends Command {
// or without __constructor as mentioned by scrowler if you dont
// need to do additional coding with __contructor params
// can be protected
protected function do_command(){
echo __CLASS__, '::BAR';
}
}
class BazCommand extends Command {
public function __construct( $params ){
parent::__construct( $params );
// do something as well
}
// it cannot be private
private function do_command(){
echo __CLASS__, '::BAZ';
}
}
答案 1 :(得分:2)
请查看命令设计模式。您也可以使用之前建议的抽象工厂模式来实例化要执行的命令。
详细说明我的答案。 让我们的客户端类调用入站控制器。控制器的责任是捕获请求并将其路由到正确的操作,在这种情况下触发命令。 但是如果你看一下代码,控制器实际上是决定在它接收的某个输入中实例化什么类型的命令。如果由于某种原因命令类的构造函数发生更改,那么您还必须更改入站控制器类中的代码,因为它现在还负责实例化要执行的命令对象。 如果您实现了一个抽象工厂并注入到您的控制器中,那么您将所需的输入传递给您的工厂,以决定应该实例化哪个命令并将其传递给控制器。控制器只是触发它从工厂收到的命令,而不必担心命令是如何实例化的或命令的类型。控制器获得执行命令的请求,将命令的实例化委托给工厂,并且一旦命令由工厂交给控制器,它就被执行。 单一责任原则是最好的。抽象工厂负责实例化命令。控制器负责处理请求,在这种情况下,执行工厂返回的命令。
通过查看代码,人们已经可以看到他正在以某种方式使用Command设计模式。以下是维基百科的定义:Command design pattern
答案 2 :(得分:0)
您在代码中实现的是MVC路由器。目前你硬编码路线。相反,您还可以依靠自动加载为控制器实例化选择正确的类。如果该类不存在则回退将使事情变得健壮。两个优点:
易于扩展,您只需在由命名约定命名的文件中添加控制器类
添加其他控制器时,您根本不需要触摸路由器
你会在互联网上找到很多关于这方面的例子。自动加载功能也有详细记录。
玩得开心!