php - 这个 OOD 实现正确吗?

标签 php oop design-patterns solid-principles

我正在学习 OO SOLID 原则和设计模式,我想对此进行一些练习。因此,我从正在进行的项目中发现了一个问题,并尝试设计它。请检查它是否正确实现,或者是否过度设计,或者我实现得不好。您的回应是最重要的。

问题 我必须在一个系统中管理短信和电子邮件事件。我的意思是说将其存储在数据库中并检索它等等。

所以我认为营销事件会有一些特定的东西,比如创建日期状态等。因此我创建了一个名为营销事件模型的类,它负责与营销事件相关的一些常见功能

Class CampaignModel
{
    public function save($data)
    {
        // add campaign specific data
        // save the campaign.

    }

    public function get()
    {
        // select the row from database and return it.

    }
}

然后我进行短信营销事件和电子邮件营销事件

class SMSCampaignModel extends CampaignModel
{
    public function save($data)
    {
        // add sms specific data and
        parent::save($data);
    }

    public function gets()
    {
        //fire the query to get the sms campaigns and returns it.
    }
}

class EmailCampaignModel extends CampaignModel
{
    public function save($data)
    {
        // add email  specific data
        parent::save($data);
    }

    public function gets()
    {
        //fire the query to get the email campaigns and returns it.
    }

}

现在每个事件都会有收件人,我们必须存储每个收件人的状态,例如他打开邮件或邮件/短信已发送或失败等。我认为我们将发送包含许多电子邮件或号码的事件,因此我决定创建不同的数据库表用于存储诸如 sms_campaign_log、email_campaign_log 等详细信息。我已经为其创建了接口(interface)

interface CampaignLogs
{
    function insert_log();
    function get_details();
}

class SmsCampaignLogs implements CampaignLogs
{
    public function insert_log($data)
    {
        // get the number and status save it into the sms logs table.
    }

    public function get_details($campagin_id)
    {
        // get the logs from campagin table and return it.
    }
}

class EmailCampaignLogs implements CampaignLogs
{
    public function insert_log($data)
    {
        // get the number and status save it into the email logs table.
    }

    public function get_details($campagin_id)
    {
        // get the logs from campagin table and return it.
    }
}

最后我想现在我应该使用策略模式来实现它(我不知道它是否正确)。

class Campaign
{
    private $log;
    private $campaign_type;
    public function __construct($campaign, $logger)
    {
        $this->campaign_type = $campaign;
        $this->log  = $logger;
    }

    public function save($data)
    {
        $this->campagin_type->save();

    }
    public function gets()
    {
        $this->campaign_type->gets();
    }

    public function log($data)
    {
        $this->log->insert_log($data);
    }

    public function get_campaign_details($campaign_id)
    {
        $this->log->get_details($campaign_id);
    }
}

现在实现代码。

$campaign = new SmCampaignModel();
$logger = new SmsCampaignLogs();
$c = new Campaign($campagin,$logger);
$c->save($data);
$c->get($campaign_id);
$c->get_campaing_details();

然后我想是否需要策略模式。 简单地说,我可以实现:

    $campaign = new SmCampaignModel();
    $logger = new SmsCampaignLogs();
    $campaign->save($data);
    $campaign->get($campaign_id);
    $logger->get_campaing_details($campaign_id);

所以我现在完全困惑了。我想听听您对我在设计中是否正确应用了 SOLID 原则(以及是否需要/正确使用策略模式)的意见。

最佳答案

在这种情况下,您的 Campaign 类只是一个 Facade。没有使用任何策略。

您实际上使用的是外观模式而不是策略。您的 Campaign 类没有自己的行为。它只是将其行为委托(delegate)给子系统组件。这并不是一件坏事,但它使您的代码在某种程度上更难以维护。在信息隐藏方面还是不错的。

OOD 没有对错之分。如果没有给出理由,则不必包含设计模式。你应该问自己:“我的主要问题是什么,这能解决它吗?”。 “代码经常更改会有什么原因吗?”。

因为我们有时都想过度使用设计模式,所以我想向您展示如何建立一个简单的 OO 关系就可以很好地工作,甚至更容易阅读和维护。

abstract class Campaign {

    protected $ages;
    protected $countries;
    protected $dailyBudget;

    protected $recipientsStatus = array(); // associative array or a composition of Recipients object

    public function startCampaign()
    {
        // check there is not another run
        $this->executeCampaign();
        $this->collectRecipientsStatus();
        $this->generateStatistics();
    }

    abstract protected function executeCampaign();
    abstract protected function collectRecipientsStatus();
    abstract protected function generateStatistics();

}

class EmailCampaign extends Campaign {

    protected $addresses;

    protected function executeCampaign()
    {
        $this->filterEmailsByCampaignData();
        $this->sendEmails();
    }

    protected function filterEmailsByCampaignData()
    {
        // populate $this->addresses based on ages, countries etc.
    }

    protected function sendEmails()
    {
        // send email to addresses
    }

    protected function collectRecipientsStatus()
    {
        // collect status and fill parent $recipientsStatus
    }

    protected function generateStatistics()
    {
        // generate statistics
    }
}

Campaign 现在是一个包含数据和行为的类。我们不必将其解耦为模型和日志等组件。这会工作得很好。但是,如果您发现自己有一个更复杂的 Recipients 数组(太多键值或维数组代码味道),那么您可以将其解耦到另一组类中。但这应该随着代码的演变而发生。我们根本无法提前预见一切。

顺便说一句,我使用的唯一模式是轻量级模板方法,以及 OOP 的继承特性。

关于php - 这个 OOD 实现正确吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31423819/

相关文章:

php - 如何使用 jQuery 将磅转换为千克?

PHP - 不能在类方法中使用 Heredoc?

PHP 不会渲染 - Python Tornado

c++ - 继承 c++ 子父

java - 如何改进 builder 模式?

php - 我无法在 php 中多次执行相同的函数

java - 使用 JNA,如何创建 'C++ class' 并将其传递给 C++ 函数?

java - 静态方法与静态数据

c# - 宽容格式设计模式 - JQuery 或 C# 库?

java - 具有多个表的 ContentProvider