如何在面向服务的架构中处理Java多态性

2022-09-03 14:38:16

在面向服务的体系结构中处理实体类型的多态性和继承时,最不邪恶的路径是什么?

SOA的一个原则(据我所知)是将实体类作为纯粹的数据构造,缺乏任何业务逻辑。所有业务逻辑都包含在范围窄、松散耦合的服务中。这意味着服务实现尽可能小,从而进一步推动松散耦合,并意味着实体不必了解系统可能对它们执行的每个行为。

由于Java在决定使用哪种重载方法时使用声明的类型的决定非常令人困惑,因此服务实现中的任何多态行为都被替换为一系列条件检查或使用。这在OOPL中似乎相当落后。object.getClass()instanceof

条件语句的使用是 SOA 中公认的规范吗?是否应放弃实体中的继承?

更新

我绝对意味着超载而不是覆盖。

我将SOA定义为系统的行为按用例分组到接口中,然后这些接口的逻辑通常在每个接口的一个类中实现。因此,一个实体类(比如说)只不过是一个带有 getter 和 setter 的 POJO。它绝对不应该包含任何与服务相关的业务逻辑,因为这样你就会引入一个耦合的焦点,实体类需要知道可能在其上运行的所有业务流程,这完全否定了松散耦合SOA的目的。Product

因此,由于不应在实体类中嵌入特定于业务流程的行为,因此不能对这些实体类使用多态性 - 没有要覆盖的行为。

更新 2

上述行为可以更简单地解释为在编译时选择重载路径,在运行时选择重写路径。

为它所操作的域模型类的每个子类型都有一个服务实现的子类将是不好的做法,那么人们如何解决编译时重载的问题呢?


答案 1

您可以通过基于实体类型在不同类中设计业务逻辑来避免此问题,基于单一责任原则,当您将业务逻辑放在服务层并使用工厂创建逻辑实现时,这将是最好的方法,例如

enum ProductType
{
    Physical,
    Service
}


interface IProduct
{
    double getRate();
    ProductType getProductType();    
}

class PhysicalProduct implements IProduct
{
    private double rate;

    public double getRate()
    {
        return rate;
    }

    public double getProductType()
    {
        return ProductType.Physical;
    }
}

class ServiceProduct implements IProduct 
{
    private double rate;
    private double overTimeRate;
    private double maxHoursPerDayInNormalRate;

    public double getRate()
    {
        return rate;
    }

    public double getOverTimeRate()
    {
        return overTimeRate;
    }

    public double getMaxHoursPerDayInNormalRate;()
    {
        return maxHoursPerDayInNormalRate;
    }

    public double getProductType()
    {
        return ProductType.Service;
    }
}

interface IProductCalculator
{
    double calculate(double units);
}

class PhysicalProductCalculator implements IProductCalculator
{
    private PhysicalProduct product;

    public PhysicalProductCalculator(IProduct product)
    {
        this.product = (PhysicalProduct) product;
    }

    double calculate(double units)
    {
        //calculation logic goes here
    }
}

class ServiceProductCalculator implements IProductCalculator
{
    private ServiceProduct product;

    public ServiceProductCalculator(IProduct product)
    {
        this.product = (ServiceProduct) product;
    }

    double calculate(double units)
    {
        //calculation logic goes here
    }
}

class ProductCalculatorFactory
{
    public static IProductCalculator createCalculator(IProduct product)
    {
        switch (product.getProductType)
        {
            case Physical:
                return new PhysicalProductCalculator ();
            case Service:
                return new ServiceProductCalculator ();
        }
    }
}

//this can be used to execute the business logic
ProductCalculatorFactory.createCalculator(product).calculate(value);

答案 2

我花了一段时间从阅读这篇文章来弄清楚你真正想要的是什么。

我的解释是,你有一组 POJO 类,当传递给服务时,你希望服务能够根据传递给它的特定 POJO 类执行不同的操作。

通常,我会尝试避免使用宽或深的类型层次结构,并处理需要一个或两个案例的实例等。

当出于某种原因必须有一个宽类型层次结构时,我可能会使用如下所示的处理程序模式。

class Animal {

}
class Cat extends Animal {

}

interface AnimalHandler {
    void handleAnimal(Animal animal);
}

class CatHandler implements AnimalHandler {

    @Override
    public void handleAnimal(Animal animal) {
        Cat cat = (Cat)animal;
        // do something with a cat
    }

}

class AnimalServiceImpl implements AnimalHandler {
    Map<Class,AnimalHandler> animalHandlers = new HashMap<Class, AnimalHandler>();

    AnimalServiceImpl() { 
        animalHandlers.put(Cat.class, new CatHandler());
    }
    public void handleAnimal(Animal animal) {
        animalHandlers.get(animal.getClass()).handleAnimal(animal);
    }
}