在面向服务的体系结构中处理实体类型的多态性和继承时,最不邪恶的道路是什么?
SOA的原则(据我所知)是将实体类仅仅作为数据结构,缺乏任何业务逻辑。所有业务逻辑都包含在窄范围,松散耦合的服务中。这意味着服务实现尽可能地进一步扩展松散耦合,并且意味着实体避免必须知道系统可能对它们执行的每个行为。
Due to Java's quite baffling decision to use the declared type when deciding which overloaded method to use,服务实现中的任何多态行为都会被一系列条件检查object.getClass()
或使用instanceof
替换。在OOPL中,这似乎相当落后。
条件的使用是否是SOA中公认的标准?是否应该放弃实体中的继承?
更新
我绝对意味着超载而不是覆盖。
我将SOA定义为系统行为按用例分组到接口中,然后通常每个接口在一个类中实现这些行为的逻辑。因此,实体类(比如说Product
)只不过是一个带有getter和setter的POJO。它绝对不应该包含任何与服务相关的业务逻辑,因为那时你引入了一个耦合焦点,实体类需要知道可能在其上运行的所有业务流程,完全否定松散耦合SOA的目的
因此,如果不应该在实体类中嵌入特定于业务流程的行为,则不能对这些实体类使用多态 - 没有要覆盖的行为。
更新2
上述行为更简单地解释为编译时选择了重载路径,处的重写路径运行时即可。
为它所处理的域模型类的每个子类型设置一个服务实现的子类是不好的做法,那么人们如何解决编译时的重载问题呢?
答案 0 :(得分:5)
您可以通过基于实体类型在不同类中设计业务逻辑来避免此问题,基于单一责任原则,当您将业务逻辑放在服务层并使用工厂创建时,这将是最佳方式逻辑实现,例如
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);
答案 1 :(得分:3)
由于Java在使用声明类型时非常莫名其妙 决定使用哪种重载方法
谁给了你这个主意?如果像那样,Java将是一种毫无价值的语言!
阅读本文:Java Tutorial > Inheritance
这是一个简单的测试程序:
public class Tester{
static class Foo {
void foo() {
System.out.println("foo");
}
}
static class Bar extends Foo {
@Override
void foo() {
System.out.println("bar");
}
}
public static void main(final String[] args) {
final Foo foo = new Bar();
foo.foo();
}
}
答案 2 :(得分:2)
我认为这里有一些令人困惑的问题。 SOA是解决组件之间交互的架构方式。 SOA解决方案中的每个组件都将处理更大域中的上下文。每个上下文都是它自己的领域。换句话说,SOA允许在域上下文或应用程序之间失去耦合。
在这种环境中工作时,Java中的面向对象将适用于每个域。因此,使用域驱动设计等方式建模的层次结构和丰富域对象将生活在SOA解决方案中的服务之下。在公开其他上下文的服务和详细的域模型之间有一个层,它将为域创建丰富的对象。
使用SOA解决每个上下文/应用程序架构将无法提供非常好的应用程序。正如使用OO解决它们之间的相互作用一样。
所以试着更具体地回答赏金问题: 这不是围绕这个问题进行工程设计的问题。这是在每个设计层面应用正确模式的问题。
对于大型企业生态系统,SOA是解决系统之间交互的方式,例如人力资源系统和工资单。但是当与HR(或可能是HR中的每个上下文)和工资单一起使用时,我会使用来自DDD的模式。
我希望稍微清除水域。
答案 3 :(得分:2)
我花了一些时间阅读这篇文章来找出你真正需要的东西。
我的解释是你有一组POJO类,当传递给服务时,你希望服务能够执行不同的操作,具体取决于传递给它的特定POJO类。
通常我会尝试避免广泛或深层次的层次结构,并处理需要一两个案例的instanceof等。
当出于任何原因必须有一个宽类型层次结构时,我可能会使用类似下面的处理程序模式。
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);
}
}
答案 4 :(得分:1)
考虑到这一点后,我想到了一种可以简化设计的替代方法。
abstract class Animal {
}
class Cat extends Animal {
public String meow() {
return "Meow";
}
}
class Dog extends Animal {
public String bark() {
return "Bark";
}
}
class AnimalService {
public String getSound(Animal animal) {
try {
Method method = this.getClass().getMethod("getSound", animal.getClass());
return (String) method.invoke(this, animal);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getSound(Cat cat) {
return cat.meow();
}
public String getSound(Dog dog) {
return dog.bark();
}
}
public static void main(String[] args) {
AnimalService animalService = new AnimalService();
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Cat());
animals.add(new Dog());
for (Animal animal : animals) {
String sound = animalService.getSound(animal);
System.out.println(sound);
}
}