簡體   English   中英

如何使我的MailingList管理器類更加松散耦合?

[英]How can I make my MailingList manager class more loosly coupled?

我正在開展一個涉及前景優惠的簡單項目。 該項目將與第三方郵件列表提供程序集成,后者將使用Prospect對象管理列表中的電子郵件地址,並提供管理廣告系列的對象。

我擔心的一個問題是任何郵件列表提供商(例如,MailChimp)可能決定停止提供他們的服務,或者將來更改條款。 我不想讓我的軟件依賴於提供程序,而是希望它依賴於通用接口,該接口可以使用不同的類重新實現,該類使用不同的郵件列表提供程序。 這樣,如果發生了這種情況,我只需編寫一個新類並實例化舊類即可。

這似乎很容易實現。 我的抽象類(包含在下面)定義了抽象方法,這些方法接受Prospect或Offer對象,並為它們執行通用的郵件列表相關函數,在需要時返回true / false或整數值。 該接口應該可以很好地滿足我的應用程序的需求。

<?php
/**
 * MailingList file.
 *
 * Contains the class definition for the abstract class Monty_MailingList.
 * @author Lewis Bassett <lewis.bassett@bassettprovidentia.com>
 * @version 0.1
 * @package Monty
 */

/**
 * Represents the interface for all MailingList classes.
 *
 * Adhereing to this interface means that if a MailingList provider
 * (e.g., MailChimp) stops a service, a new class can extend this interface and
 * be replace the obsolete class with no need to modify any of the client code.
 *
 * @author Lewis Bassett <lewis.bassett@bassettprovidentia.com>
 * @version 0.1
 * @package Monty
 * @copyright Copyright (c) 2011, Bassett Providentia
 */
abstract class Monty_MailingList
{
    /**
     * Adds the passed prospect to the mailing list, or returns false if the
     * prospect already exists. Throws an error if the prospect could not be
     * added for any reason (other than it already existing).
     *
     * @param Monty_Prospect $prospect The prospect object to be added to the
     * mailing list.
     * @return bool Whether or not the prospect was added.
     */
    abstract public function addProspect(Monty_Prospect $prospect);

    /**
     * Updates the properties stored on the mailing list of the passed prospect,
     * or returns false if no data was updated. If the prospect is not found, a
     * they are added to the list. Throws an error if the prospect could not be
     * added or updated for any readon.
     *
     * @param Monty_Prospect $prospect The prospect object whose mailing list
     * data is to be updated.
     * @return bool Whether or not the prospect was updated.
     */
    abstract public function updateProspect(Monty_Prospect $prospect);

    /**
     * Returns true if the passed prospect object could be found on the mailing
     * list.
     *
     * @param Monty_Prospect $prospect The prospect object to be searched for.
     * @return bool Whether or not the prospect was found.
     */
    abstract public function findProspect(Monty_Prospect $prospect);

    /**
     * Deletes the passed prospect from the mailing list, or returns false if
     * the passed object is not found on the mailing list.
     *
     * @param Monty_Prospect $prospect The prospect to be deleted.
     * @return bool Whether or not the prospect was deleted.
     */
    abstract public function deleteProspect(Monty_Prospect $prospect);

    /**
     * Creates a campaign for the passed offer object, or returns false if the
     * campaign already exists. Throws an error if the campaign could not be
     * created for any reason (other than it already existing).
     *
     * @param Monty_Offer $offer The offer to be created.
     * @return bool Whether or not the offer was created.
     */
    abstract public function createOffer(Monty_Offer $offer);

    /**
     * Sends the campaign for the passed offer object, or returns false if the
     * campaign could not be sent for a reasonable reason (run out of credit or
     * something). If the campaign does not yet exist, it is created. Throws an
     * error if the campaign could not be created, or an was not sent for an
     * unknown reason.
     *
     * @param Monty_Offer $offer The offer to be sent.
     * @return bool Whether or not the offer was sent.
     */
    abstract public function sendOffer(Monty_Offer $offer);

    /**
     * Returns true if a campaign for the passed offer object could be found on
     * the mailing list.
     *
     * @param Monty_Offer $offer The offer to be searched for,
     * @return bool Whether or not the offer was found.
     */
    abstract public function findOffer(Monty_Offer $offer);

    /**
     * Returns the ammount of opens registered for the passed offer. Throws an
     * error if a campaign is not found for the passed offer.
     *
     * @param Monty_Offer $offer The offer in question.
     * @return int The ammount of registered opens for that offer.
     */
    abstract public function getOfferOpens(Monty_Offer $offer);

    /**
     * Returns the ammount of clicks registered for the passed offer. Throws an
     * error if a campaign is not found for the passed offer.
     *
     * @param Monty_Offer $offer The offer in question.
     * @return int The ammount of registered clicks for that offer.
     */
    abstract public function getOfferClicks(Monty_Offer $offer);

    /**
     * Returns the ammount of bounces registered for the passed offer. Throws an
     * error if a campaign is not found for the passed offer.
     *
     * @param Monty_Offer $offer The offer in question.
     * @return int The ammount of registered bounces for that offer.
     */
    abstract public function getOfferBounces(Monty_Offer $offer);

    /**
     * Returns the ammount of unsubscribes registered for the passed offer.
     * Throws an error if a campaign is not found for the passed offer.
     *
     * @param Monty_Offer $offer The offer in question.
     * @return int The ammount of registered unsubscribes for that offer.
     */
    abstract public function getOfferUnsubscribes(Monty_Offer $offer);
}

困境來了。

將來,我的應用程序郵件列表提供程序之間傳遞的數據可能會發生變化,但是,我不希望不得不隨時隨地更改界面。 通過將對象傳遞到方法中,我可以修改方法以在新屬性可用時使用它們,而無需在任何地方更改接口。 這似乎是一個非常靈活的解決方案。

我想在其他項目中使用此類,這些項目可能不一定使用Prospect或Offer類。 從類的角度來看,上面的接口似乎過於緊密耦合,因為類依賴於傳遞給它的對象。

有沒有人對如何保持將對象傳遞給方法的靈活性有任何建議,但有一個我可以輕松地重用於其他項目的類?

非常感謝,如果您已經閱讀了到目前為止! 我一直在努力提高自己的技能,也非常感謝您對我如何做得更好的見解。

如果您想要更通用的方法,請創建一個類,您可以在其中添加而不是潛在客戶,並創建電子郵件而不是商品,即(任意)郵件列表的通用接口。 然后讓你的Monty_MailingList繼承通用列表。

我在某種程度上同意埃米爾的觀點。

你在這里混淆了這些問題。 您的課程稱為郵件列表,其中不包含潛在客戶和優惠,但包含您要發送的人員和內容。

前景和優惠是業務邏輯模型,可以通過電子郵件將一個表示發送給用戶,因為他們可以在呈現到網頁時具有其他表示。 從郵件中收集統計數據也是分開的事情。

我不同意的一件事是在繼承點上,而我從不這樣做。 我不會在這里繼承任何東西,而是創建單獨的類來處理其部分並改為使用組合。

經過更多的思考,由於設計模式的啟發,我提出了我認為是最佳的解決方案:可重用的面向對象軟件的元素 (Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides)。

我現在有兩個抽象類:

MailingListRecipient-定義對象的接口,這些對象將代表郵件列表的收件人。 所有客戶端代碼都將為此接口編寫,而不管此抽象代碼的哪個子類實現該接口。 它將具有設置姓氏,姓氏和電子郵件地址,以及在郵件列表中添加,更新,刪除和查找收件人的方法。

MailingListMessage-定義對象的接口,這些對象將表示郵件列表上的消息,並定義了一些設置方法和一些操作。 同樣,將為此接口編寫客戶端代碼,而不關心子類如何實現它。

然后,我將有一個抽象工廠類:

MailingListFactory-這將在我的所有客戶端代碼中創建MailingListRecipientMailingListMessage對象。

因此,對於一個實際的實現,我將創建:

MailChimpRecipient - 表示MailChimp列表中的收件人。 此處的代碼將遵循MailingListRecipient定義的接口,並且該對象的構造函數中需要API密鑰和ListId。

MailChimpMessage - 表示MailChimp列表中的消息。 這里的代碼將遵循MailingListMessage定義的接口,並且該對象在其構造函數中也將需要API密鑰和ListId。

我的客戶端代碼不會與上述兩個對象中的任何一個進行交互。 相反,在我的一個設置文件中,我將創建一個對象:

MailChimpFactory - 用於創建MailChimp收件人和郵件。 該對象將需要API密鑰和ListId,並將依次將這些傳遞給上述兩個類的構造函數,以便創建MailChimp特定對象。

所以,在我的設置代碼中,我將創建一個工廠對象:

$mailingListFactory = new MailChimpFactory($apiKey, $listId);

然后,在我的客戶端代碼中,將創建新的收件人和消息:

$recipient = $mailingListFactory->createMailingListRecipient();

從那時起,它將能夠設置和執行操作:

$recipient->setForename('Lewis');
$recipient->setEmailAddress('lewis@example.com');
$recipient->add();

如果MailChimp突然停止其服務,或者我決定使用其他郵件列表提供程序,我將創建使用新提供程序的MailingListRecipient和MailingListMessage的新子類-它們的接口將相同,並且客戶端代碼將不知道或者關心它是不同的。

然后,我將創建一個新的MailingListFactory子類,該子類將創建新類的新的收件人和消息對象。 我需要做的就是更改設置文件中的實例化:

$mailingListFactory = new newMailingListProviderFactory($username, $password);

由於我的其余代碼是為抽象工廠中定義的接口編寫的,因此無需進行其他任何更改。

使用抽象工廠可確保我不會遇到代碼使用mailChimpRecipient對象和newMailingListProviderMessage對象的情況。

這符合我的目標:

互換性-我可以交換郵件列表類,並且代碼仍然可以像以前一樣工作;

可重用性 - 我可以使用這些類並在其他項目中使用它們。

這似乎是最優雅的方式。 如果其他人有更好的方式,我很樂意聽到它。 感謝大家的回復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM