Php 如何使我的邮件列表管理器类更紧密地耦合?
我正在做一个简单的项目,涉及潜在客户和报价。该项目将与第三方邮件列表提供商集成,后者将使用Prospect对象管理列表上的电子邮件地址,并提供对象来管理活动 我担心的一个问题是,任何邮件列表提供商(例如MailChimp)可能会决定停止提供服务,或者在将来更改条款。我不想让我的软件依赖于提供者,而是想让它依赖于一个通用接口,这个接口可以使用一个使用不同邮件列表提供者的不同类重新实现。这样,如果真的发生了这样的事情,我只需编写一个新类并在旧类的位置进行实例化 这似乎很容易实现。我的抽象类(包含在下面)定义了抽象方法,这些方法接受Prospect或Offer对象,并对它们执行与通用邮件列表相关的函数,在需要时返回真/假或整数值。这个接口应该很好地满足我的应用程序的需要Php 如何使我的邮件列表管理器类更紧密地耦合?,php,object,loose-coupling,Php,Object,Loose Coupling,我正在做一个简单的项目,涉及潜在客户和报价。该项目将与第三方邮件列表提供商集成,后者将使用Prospect对象管理列表上的电子邮件地址,并提供对象来管理活动 我担心的一个问题是,任何邮件列表提供商(例如MailChimp)可能会决定停止提供服务,或者在将来更改条款。我不想让我的软件依赖于提供者,而是想让它依赖于一个通用接口,这个接口可以使用一个使用不同邮件列表提供者的不同类重新实现。这样,如果真的发生了这样的事情,我只需编写一个新类并在旧类的位置进行实例化 这似乎很容易实现。我的抽象类(包含在下
<?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);
}
如果您想要更通用的方法,请创建一个类,在该类中添加人员而不是潜在客户,并添加电子邮件而不是提供,即(任何)邮件列表的通用接口。然后让你的Monty_邮件列表继承通用列表。我在某些方面同意Emil的观点
你在这里混淆视听。您的类称为邮件列表,它应该和潜在客户和提供的内容无关,但包含您希望发送给他们的人员和内容
Prospect和Offers是业务逻辑模型,可以通过电子邮件向用户发送一个表示,因为在呈现到web页面时,用户可以使用另一个表示。从邮件中收集统计数据也是另外一回事
有一件事我不同意,那就是关于继承的问题,因为我通常不会这么做。在这里,我不会继承任何东西,而是创建单独的类来处理它们的部分并使用组合。经过进一步思考,我想出了我认为最好的解决方案,这要归功于设计模式的一些灵感:可重用面向对象软件的元素(埃里克·伽马、理查德·赫尔姆、拉尔夫·约翰逊和约翰·维利塞德斯)
我现在有两个抽象类:
MailingListRecipient-为表示邮件列表收件人的对象定义接口。所有客户端代码都将为此接口编写,不关心此抽象代码的哪个子类实现它。它将具有设置名字、姓氏和电子邮件地址以及添加、更新、删除和删除的方法在邮件列表中找到收件人
MailingListMessage-为将在邮件列表上表示消息的对象定义接口,并将定义一些setter方法和一些操作。同样,将为此接口编写客户端代码,而不关心子类如何实现它
然后我将有一个抽象的工厂类:
MailingListFactory-这将在我的客户端代码中创建MailingListRecipient和MailingListMessage对象
因此,对于真正的实现,我将创建:
MailChimpRecipient-在MailChimp列表上表示收件人。此处的代码将遵循MailingListRecipient定义的接口,并且对象在其构造函数中需要API键和ListId
MailChimpMessage-表示MailChimp列表上的消息。此处的代码将遵循MailingListMessage定义的接口,并且此对象在其构造函数中也需要API键和ListId
我的客户端代码不会与上面两个对象中的任何一个进行交互。相反,在我的一个设置文件中,我将创建以下对象:
MailChimp工厂-用于创建MailChimp收件人和邮件。对象需要API键和ListId,然后将它们传递给上述两个类的构造函数,以创建MailChimp特定的对象
因此,在我的设置代码中,我将创建一个factory对象:
$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对象的情况
这符合我的两个目标:
可互换性-我可以交换我的邮件列表类,代码仍然可以像以前一样工作
可重用性——我可以使用这些类并在其他项目中使用它们
这似乎是最优雅的方式。如果其他人有更好的方式,我很乐意听到。谢谢大家的回复。构图是另一种方式,是的,但我认为继承是首选方式,因为他实际上想要一个特殊的邮件列表,您可以在其中添加潜在客户和优惠。构图更重要这是一种必要的方式,事实上,它确实使代码更紧密地耦合,因为潜在客户/报价列表需要将通用邮件列表作为其参数(如果他稍后将通用列表发送到其他地方会发生什么情况?潜在客户是否神奇地与其他类型的人联系在一起?)。如果