【问题标题】:Modelling class hierarchy建模类层次结构
【发布时间】:2017-09-25 03:17:32
【问题描述】:

我目前正在建模一个类层次结构,所以想检查是否有人有更好的方法来做到这一点。问题如下:

我有一个菜单项,里面有 id 和图标。然后我也可以拥有具有其他子菜单项的菜单项(但同时没有图标)。它基本上是子菜单项的容器,但也有 id 作为真正的菜单项。当前模型是这样的:

class SubMenuItemOrderNumber{}
class MenuItemTypeId{}
class MenuIconId{}
class MenuIcon{}

interface MenuItemWithoutSubItems{
    MenuItemTypeId getTypeId();
    List<MenuIcon> getIcons();
}

interface MenuItemWithSubItems{
    MenuItemTypeId getTypeId();
    Map<SubMenuItemOrderNumber, SubMenuItem> getOrderNumToSubMenuItem();
}

interface SubMenuItem{
    SubMenuItemOrderNumber getOrderNum();
    List<MenuIcon> getIcons();
}

interface Publishable{
    void suspend();
    void publish();
}

interface ControllableMenuItemWithoutSubItems extends MenuItemWithoutSubItems, Publishable{
    void control(MenuIconId iconId, String iconData);
}

interface ControllableMenuItemWithSubItems extends MenuItemWithSubItems, Publishable{
    void control(SubMenuItemOrderNumber orderNum, MenuIconId iconId, String iconData);
}

问题 - 似乎我可以让它更通用。我唯一想到的就是这种变化:

    enum EnumSubMenuItemOrderNumber implements SubMenuItemOrderNumber{
    ONLY_IF_MENU_ITEM_WITHOUT_SUB_ITEMS(0);
    private int num;
    EnumSubMenuItemTypeId(num id){
        this.num = num;
    }
    @Override
    public Integer getNum() {
        return num;
    }
}

class RealSubMenuItemOrderNumber implements SubMenuItemOrderNumber{
    private int num;
    @Override
    public Integer getNum() {
        return num;
    }
}

interface SubMenuItemOrderNumber{
    Integer getNum();
}

class MenuItemTypeId{}
class MenuIconId{}
class MenuIcon{}

interface MenuItem{
    MenuItemTypeId getTypeId();
    Map<SubMenuItemOrderNumber, SubMenuItem> getOrderNumToSubMenuItem();
}

interface SubMenuItem{
    SubMenuItemOrderNumber getOrderNum();
    List<MenuIcon> getIcons();
}

interface Publishable{
    void suspend();
    void publish();
}

interface ControllableMenuItem extends MenuItem, Publishable{
    void control(SubMenuItemOrderNumber orderNum, MenuIconId iconId, String iconData);
}

但是问题在于,如果我想要MenuItemWithoutSubItems,我必须在Map 中创建MenuItemSubMenuItemTypeId,我必须使用EnumSubMenuItemTypeId.ONLY_IF_MENU_ITEM_WITHOUT_SUB_ITEMS -> 在我的情况下这是一种解决方法。类更简单,但它似乎仍然比需要的复杂。

我还有其他选择吗?

更新

这是第一个用例的潜在实现:

class DefaultMenuItemWithoutSubItems implements MenuItemWithoutSubItems {
    MenuItemTypeId id;
    List<MenuIcon> menuIcons;

    @Override
    public MenuItemTypeId getTypeId() {
        return id;
    }

    @Override
    public List<MenuIcon> getIcons() {
        return menuIcons;
    }
}

class DefaultMenuItemWithSubItems implements MenuItemWithSubItems {
    MenuItemTypeId id;
    Map<SubMenuItemOrderNumber, SubMenuItem> orderNumToSubMenuItem;

    @Override
    public MenuItemTypeId getTypeId() {
        return id;
    }

    @Override
    public Map<SubMenuItemOrderNumber, SubMenuItem> getOrderNumToSubMenuItem() {
        return orderNumToSubMenuItem;
    }
}

class DefaultSubMenuItem implements SubMenuItem {
    SubMenuItemOrderNumber orderNum;
    List<MenuIcon> menuIcons;

    @Override
    public SubMenuItemOrderNumber getOrderNum() {
        return orderNum;
    }

    @Override
    public List<MenuIcon> getIcons() {
        return menuIcons;
    }
}

class DefaultControllableMenuItemWithoutSubItems implements ControllableMenuItemWithoutSubItems {
    MenuItemTypeId id;
    List<MenuIcon> menuIcons;
    boolean suspended;

    @Override
    public MenuItemTypeId getTypeId() {
        return id;
    }

    @Override
    public List<MenuIcon> getIcons() {
        return menuIcons;
    }

    @Override
    public void suspend() {
        suspended = true;
    }

    @Override
    public void publish() {
        suspended = false;
    }

    @Override
    public void control(MenuIconId iconId, String iconData) {
        menuIcons.getById(iconId).replace(new MenuIcon(iconData));
    }
}

【问题讨论】:

    标签: java oop design-patterns data-modeling


    【解决方案1】:

    这看起来像是使用复合模式的失败尝试。 这是复合模式背后的想法:

    您有一个要公开的接口。例如:

    public interface MenuItem {
        MenuItemTypeID getType();
        List<MenuIcon> getIcons();
    }
    

    接下来你有一个基本的实现:

    class SingleMenuItem implements MenuItem {
        private MenuItemTypeID id;
        private List<MenuIcon> icons;
    
        public SingleMenuItem(MenuItemTypeID id, List<MenuIcon> icons) {
            this.id = id;
            this.icons = icons;
        }
    
        @Override
        public MenuItemTypeID getType() {
            return id;
        }
    
        @Override
        public List<MenuIcon> getIcons() {
            return icons;
        }
    }
    

    魔法来了。我们还希望有一个分组实现,但是复合模式要求它的行为应该与普通的 MenuItem 完全一样。所以这个类可能看起来像这样:

    class MenuItemGroup implements MenuItem {
        private MenuItemTypeID id;
        private List<MenuItem> subMenuItems;
    
        public MenuItemGroup(MenuItemTypeID id, List<MenuItem> subMenuItems) {
            this.id = id;
            this.subMenuItems = subMenuItems;
        }
    
        @Override
        public MenuItemTypeID getType() {
            return id;
        }
    
        @Override
        public List<MenuIcon> getIcons() {
            List<MenuIcon> result = new ArrayList<>();
            for (MenuItem subItem : subMenuItems) {
                result.addAll(subItem.getIcons());
            }
            return result;
        }
    }
    

    现在,如果我们有一些MenuItem item,我们可以获取该菜单项中的所有图标。我们不关心它是SingleMenuItem,还是MenuItemGroup,因为两者都只会返回它们包含的所有图标。

    请注意,我们还可以有一个包含更多组的组,这些组都包含一些 SingleMenuItems,或者 SingleMenuItems 与更多组 MenuItems 的组合。我们仍然像使用任何其他 MenuItem 一样使用它。

    虽然我不知道这在您的上下文中有多大用处......

    【讨论】:

    • 我知道复合模式。您的实现的问题是您丢失了 SubMenuItemOrderNumber。此外,MenuItemGroup 中的 subMenuItems 有 MenuItemTypeId,但该属性不属于 MenuItemGroup 中的这个子项(SubItems 实际上不是我的模型中的 MenuItems)。
    • 嗯,所以这些实际上很重要,而不仅仅是一个设计工件......你能提供一个具体的例子吗?由于您现在只有接口,我不明白它们将如何实际使用。
    • 我刚刚添加了潜在的实现。现在,我认为我需要分别访问这两个对象。我会将它们存储在 2 个不同的列表中,然后我必须知道哪个没有子项,哪个有(因为在具有子项的列表中,我实际上可以对这些子项进行操作)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 2012-02-16
    • 2013-11-28
    • 2021-12-11
    • 1970-01-01
    • 2011-05-19
    相关资源
    最近更新 更多