2

我有一个设计问题,我的课程是以这种方式设置的:

abstract class Advertiser        abstract class AdvertiserCampaign
      |                                    |
      |                                    |
class AdvUno extends Advertiser  class AdvUnoCampaign extends AdvertiserCampaign
class AdvDos extends Advertiser  class AdvDosCampaign extends AdvertiserCampaign
class AdvTre extends Advertiser  class AdvTreCampaign extends AdvertiserCampaign

问题是AdvUno两者AdvUnoCampaign都需要一种对其他人来说不需要的特殊身份验证方法。现在我已经把它放在了AdvUno,但同样,它会被AdvUnoCampaign(以及以这种方式设置的一堆其他类)所需要。

  • 我无法进行AdvUnoCampaign扩展AdvUno,因为 PHP 中没有多重继承,而且还因为它通常不是一个好的、干净的设计实践。
  • 如果我进行AdvertiserCampaignextend Advertiser,那么下面的所有扩展类(AdvUnoCampaignAdvDosCampaign等)都必须实现一堆与它们无关的抽象方法,并且已经在每个Advertiser类中实现了这些方法。

简而言之,在这种情况下,最佳设计实践是什么?我宁愿不只是将代码复制并粘贴到所有AdvOne类中。任何帮助或建议将不胜感激。谢谢!

4

2 回答 2

3

并行继承层次结构被认为是一种代码异味,应该重构。

Martin Fowler 在“重构”中建议:

消除重复的一般策略是确保一个层次结构的实例引用另一个层次结构的实例。如果您使用Move MethodMove Field,则引用类的层次结构会消失。

但我认为你可以更进一步。我不知道,您为每个广告商及其广告系列制作子类的决定是基于什么,但我会质疑这个决定。一个好的做法是优先考虑组合而不是继承

你可以这样开始:

class Advertiser
{
  protected $authentication;
}

class AdvertiserCampaign
{
  protected $authentication;
}

interface AdvertiserAuthentication
{
}

class SpecialAuthenticationForAdvertiserUno implements AdvertiserAuthentication
{
}

class NoSpecialAuthenticationForOtherAdvertisers implements AdvertiserAuthentication
{
}

现在,广告商之间的第一个区别被移到另一个类别中。继续进行其他差异,直到每个广告商都只是Advertiser以不同方式组合的对象。竞选活动也是如此。我想更具体一点,但如前所述,我不知道为什么您的广告客户首先都有自己的课程。

于 2013-03-14T22:10:16.710 回答
0

通常,要解决与您类似的问题,通常使用桥接设计模式。

http://sourcemaking.com/design_patterns/bridge

于 2013-03-21T14:09:47.443 回答