Java 领域模型:具有特定子类别的类别

Java domain model: categories with specific subcategories

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

public class Product
{
    private List<Category> categories

    ...
}

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

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

public enum RedSubCategory
{
    MAROON, ORANGE, BORDEAUX;
}

public enum BlueSubCategory
{
    LIGHT, DARK, AZURE;
}

我现在正在努力创建类别 class。因为每个类别都有很好的定义,所以我想把它做成一个枚举。然而,每个枚举值都应该有一个不同子类型的子类别列表,这是行不通的:

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; 
    }
}

如果我将类别设为 a class 而不是枚举,我 运行 也会遇到同样的问题。我可以使用泛型来解决这个问题,但是我丢失了所有可能类别的静态定义。此外,如何才能使类别 RED 成为唯一可以使用 RedSubCategories 的类别?通过将 class 与泛型一起使用,没有什么可以阻止我创建具有类别 "blue" 和红色子类别的类别对象!

我可以在这里使用任何模式或 inheritance/generics 技巧吗?

可能正在使用 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:大约 "I want to ensure a product cannot have a red category but a list of blue subcategories"。

我认为您不能仅在编译时使用强制转换来做到这一点。编译器无法知道哪个主要类别将提供给 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;
        }

    }