改进PHP中的类结构而不是使用多重继承

I have a design problem where my classes are set up in such a way:

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

The problem is that AdvUno and AdvUnoCampaign both need a special authentication method that's not necessary for the others. Right now I've placed it in AdvUno, but again, it'll be needed by AdvUnoCampaign (and a bunch of other classes that are set up in this way).

  • I can't make AdvUnoCampaign extend AdvUno since there's no multiple inheritance in PHP, but also because it's just generally not a good, clean design practice.
  • If I make AdvertiserCampaign extend Advertiser, then all of the extending classes below (AdvUnoCampaign, AdvDosCampaign, etc) must implement a bunch of abstract methods that are of no concern to them, and which are already implemented in each of the Advertiser classes.

In short, what's the best design practice in this sort of situation? I'd rather not just copy and paste the code into all of the AdvOne classes. Any help or advice would be appreciated. Thanks!

Parallel Inheritance Hierarchies are considered a code smell, something that should be refactored.

Martin Fowler suggests in "Refactoring":

The general strategy for eliminating the duplication is to make sure that instances of one hierarchy refer to instances of the other. If you use Move Method and Move Field, the hierarchy on the referring class disappears.

But I think you can go one step further. I don't know, what your decision was based on to make sub classes for each advertiser and their campaigns, but I would challenge this decision. A good practise to follow is to Favor Composition over Inheritance.

You could start like that:

class Advertiser
{
  protected $authentication;
}

class AdvertiserCampaign
{
  protected $authentication;
}

interface AdvertiserAuthentication
{
}

class SpecialAuthenticationForAdvertiserUno implements AdvertiserAuthentication
{
}

class NoSpecialAuthenticationForOtherAdvertisers implements AdvertiserAuthentication
{
}

Now the first difference between the advertisers is moved into another class. Go on with other differences until each advertiser is just an object of Advertiser composed in a different way. The same goes for the campaigns. I would like to be more concrete but as stated before, I have no idea why your advertisers all have their own classes in the first place.

In general, to resolve problems similar to yours the Bridge design pattern is commonly used.

http://sourcemaking.com/design_patterns/bridge