A good design pattern for almost similar objects

2019-08-15 06:27发布

问题:

I have two websites that have an almost identical database schema. the only difference is that some tables in one website have 1 or 2 extra fields that the other and vice versa.

I wanted to the same Database Access layer classes to will manipulate both websites.

What can be a good design pattern that can be used to handle that little difference.

for example, I have a method createAccount(Account account) in my DAO class but the implementation will be slightly different between website A and website B.

回答1:

If the implementation of the objects would also be almost the same, I would suggest to use an Abstract Base Class. Extend the class by inheritance and make sure your functions that are not aware of the extended field require the base class and not the derived class.

class MercedesBenzC300 : Car
{
     int brake();
     void TurnOnRadio();
}

class MercedesBenzC300Business : MercedesBenzC300
{
    int EnableCruiseControl();
}

So in this example we have two cars which are almost exactly the same, however, one is a business edition so it has cruise controle. All functions that do not interact with the cruisecontrol can also see it as an ordinary car. Only those that should use the cruise control, should now get the derived class.



回答2:

Too few details to say something concrete, but I'll try. It depends on situation complexity, but you could be happy with simple parametrization that toggles features on/off:

class AccountRepository:
    def constructor(have_feature_a, have_feature_b, etc):
        # ...

    def create_account(account):
        if have_feature_a:
            # do something special
        # do common operations
        if have_feature_b:
            # do another special thing

This works fine if you have few such features and they do very small things (representable in few lines of code). If some of these features are heavy they can be encapsulated in separate class with known interface. That is known as Strategy pattern. Then this strategy is injected AccountRepository as a dependency. This is known as DI or Dependency Injection:

class AccountRepository:
    def constructor(have_feature_a, feature_b_worker, etc):
        # ...

    def create_account(account):
        if have_feature_a:
            # do something special
        # do common operations
        if feature_b_worker != null:
            # line bellow runs heavy code encapsulated in strategy
            feature_b_worker.do_work(account)

Now you can even have multiple FeatureB implementations and use either of them for different cases. E.g. one for tests and one for production.