vendredi 10 décembre 2021

Factory Pattern when one object can't implement the full interface and the Interface Segregation Principle

I am refactoring a code and my intention is to use the Factory Design Pattern for object creation. I am also learning about SOLID principles and trying to apply them on the go. My problem is that not all objects created by the factory implement all the methods of the interface but most of them.

Description of the application: There are three discount classes for three different materials (gold, silver and platinum). All three have a regular discount but only silver and gold have a bonus discount.

Solution 1: Same interface but breaking the Interface Segregation Principle

from abc import ABC, abstractmethod


class Discount(ABC):
    @abstractmethod
    def regularDiscount(self):
        ...

    @abstractmethod
    def bonusDiscount(self):
        ...


class SilverDiscount(Discount):
    def regularDiscount(self, price):
        return price - 20

    def bonusDiscount(self, price):
        return price * 0.98


class GoldDiscount(Discount):
    def regularDiscount(self, price):
        return price - 50

    def bonusDiscount(self, price):
        return price * 0.95


class PlatinumDiscount(Discount):
    def regularDiscount(self, price):
        return price - 20

    # Unnecesarily implemented method because platinum doesn't have bonus discount
    def bonusDiscount(self, price):
        return price


def DiscountFactory(material: str ="gold") -> Discount:
    discounts = {
        "gold": GoldDiscount,
        "silver": SilverDiscount,
        "platinum": PlatinumDiscount
    }
    return discounts[material]()

Solution 2: Two different interfaces but don't know what is the return type for the Factory

from abc import ABC, abstractmethod


class RegularDiscount(ABC):
    @abstractmethod
    def regularDiscount(self):
        ...


class BonusDiscount(ABC):
    @abstractmethod
    def bonusDiscount(self):
        ...

    
class SilverDiscount(RegularDiscount, BonusDiscount):
    def regularDiscount(self, price):
        return price - 20

    def bonusDiscount(self, price):
        return price * 0.98


class GoldDiscount(RegularDiscount, BonusDiscount):
    def regularDiscount(self, price):
        return price - 50

    def bonusDiscount(self, price):
        return price * 0.95


class PlatinumDiscount(RegularDiscount):
    def regularDiscount(self, price):
        return price - 20

# What return type to use?
def DiscountFactory(material: str ="gold") -> ?????????:
    discounts = {
        "gold": GoldDiscount,
        "silver": SilverDiscount,
        "platinum": PlatinumDiscount
    }
    return discounts[material]()

How should I solve this?

Aucun commentaire:

Enregistrer un commentaire