【问题标题】:Java domain model: categories with specific subcategoriesJava 领域模型:具有特定子类别的类别
【发布时间】:2015-11-23 12:32:46
【问题描述】:

我有一个类产品。每个产品可以有任意数量的类别:

public class Product
{
    private List<Category> categories

    ...
}

每个类别都有自己独特的子类别集。例如:

  • “红色”类别包含“栗色”、“橙色”、“波尔多”子类别
  • “蓝色”类别包含“浅色”、“深色”、“天蓝色”子类别

对于每组子类别,我创建了一个带有可能静态值的枚举:

public enum RedSubCategory
{
    MAROON, ORANGE, BORDEAUX;
}

public enum BlueSubCategory
{
    LIGHT, DARK, AZURE;
}

我现在正在努力创建 Category 类。因为每个类别都有明确的定义,所以我想将其设为枚举。但是,每个枚举值都应该有一个不同子类型的子类别列表,这是行不通的:

public enum Category
{
    RED, BLUE;

    private List<SubCategory> subCategories;

    // This won't work! SubCategory is not a real class and the 
    // SubCategory enums can't extend from a common supertype!
    public setSubCategories(List<SubCategory> subCategories)
    {
        this.subCategories : subCategories; 
    }
}

如果我将 Category 设为类而不是枚举,我会遇到同样的问题。我可以使用泛型解决这个问题,但我失去了所有可能类别的静态定义。此外,我如何使类别 RED 是唯一可以使用 RedSubCategories 的类别?通过使用具有泛型的类,没有什么能阻止我创建具有“蓝色”类别和红色子类别的类别对象!

我可以在这里使用任何模式或继承/泛型技巧吗?

【问题讨论】:

    标签: java generics inheritance enums domain-model


    【解决方案1】:

    可能正在使用java接口:

    
    
        package basic;
    
        import static basic.SubCatMain.RedSubCategory.*;
        import static basic.SubCatMain.BlueSubCategory.*;
    
        public class SubCatMain {
    
            public interface Category {
            }
    
            public enum MainCategory implements Category {
                RED(MAROON, ORANGE, BORDEAUX), 
                BLUE(LIGHT, DARK, AZURE);
    
                final private Category[] subcategories;
    
                private MainCategory(Category... subcategories) {
                    this.subcategories = subcategories;
                }
    
                public Category[] getSubcategories() {
                    return subcategories;
                }
            }
    
            public enum RedSubCategory implements Category {
                MAROON, ORANGE, BORDEAUX;
            }
    
            public enum BlueSubCategory implements Category {
                LIGHT, DARK, AZURE;
            }
    
            public static void main(String[] args) {
                // do something with your categories
            }
    
        }
    
    

    编辑

    @user1884155:关于“我想确保产品不能有红色类别而是蓝色子类别列表”。

    我认为你不能只在编译时使用强制转换来做到这一点。编译器无法知道哪个主类别将提供给 Product ctor。 需要编写一些业务规则,例如:

     
    
        public static class Product {
            final private MainCategory category;
            private Category[] categories;
    
            public Product(MainCategory category) {
                this.category = category;
            }
    
            protected void checkCategoriesAreValid(Category... categories) {
                // throw an exception if at least one of the categories 
                // is not valid in respect of some business rules
                // by default any sub-category of a main one is ok
                List refs = Arrays.asList(category.getSubcategories());
                for(Category c:categories) {
                    if (!refs.contains(c)) {
                        throw new IllegalArgumentException("...");
                    }
                }
            }
    
            public Category[] getCategories() {
                return categories;
            }
    
            public void setCategories(Category... categories) {
                checkCategoriesAreValid(categories);
                this.categories = categories;
            }
    
        }
    
    

    【讨论】:

    • 如果一个产品有类别红色,它没有所有可能的子类别,它只有一两个。所以我可以有一个产品红色 - 栗色,或一个产品红色 - 橙色,波尔多。类别不应该是枚举,但是不同的可能类型类别(红色、蓝色...)可以是枚举。我想确保产品不能有红色类别,而是蓝色子类别列表。
    • @rupesh_padhye:您使用的是什么 Java 版本?对于 Java 7 和 8,它是完美的有效代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 2019-11-28
    • 2014-08-06
    • 2016-04-24
    • 2014-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多