Я хочу расширить существующую реализацию дерева двойных связей некоторыми дополнительными данными.
Поэтому я мог бы реорганизовать базовую реализацию TreeNode
, но я хочу иметь отдельную расширенную реализацию TreeNode, потому что в моем реальном сценарии создание ExtandedTreeNode
будет намного дороже, чем построениедо базового TreeNode
, а дополнительные данные необходимы только для некоторых вариантов использования.
Рудиментный код
Вот мой первый рудиментарный подход для реализации расширяемого дерева двойных связей в Java:
Базовый интерфейс узла дерева:
interface TreeNode
{
// tree node getters:
TreeNode getParent();
List<? extends TreeNode> getChildren();
// tree node setters:
void setParent(TreeNode parentNode);
void addChild(TreeNode childNode);
// some basic operations:
boolean isSelectable();
// [...]
}
Расширенный интерфейс узла дерева:
interface ExtandedTreeNode extends TreeNode
{
// narrow types of tree node getters of super-interface:
@Override
ExtandedTreeNode getParent();
@Override
List<? extends ExtandedTreeNode> getChildren();
// narrowing types of tree node setters of super-interface is not possible!
// some additional operations:
boolean isRemoveable();
// [...]
}
Реализация базового узла дерева:
class TreeNodeImpl implements TreeNode
{
private TreeNode parent;
private List<TreeNode> children = new ArrayList<TreeNode>();
private boolean isSelectable;
//
// implement tree node getters:
//
@Override
public TreeNode getParent()
{
return parent;
}
@Override
public List<? extends TreeNode> getChildren()
{
return children;
}
//
// implement tree node setters:
//
@Override
public void setParent(TreeNode parent)
{
this.parent = parent;
}
@Override
public void addChild(TreeNode childNode)
{
children.add(childNode);
}
//
// implement basic operations:
//
@Override
public boolean isSelectable()
{
return isSelectable;
}
// [...]
}
Расширенное деревореализация узла:
class ExtandedTreeNodeImpl implements ExtandedTreeNode
{
private ExtandedTreeNode parent;
private List<ExtandedTreeNode> children = new ArrayList<ExtandedTreeNode>();
private TreeNode treeNode;
private boolean isRemoveable;
public ExtandedTreeNodeImpl()
{
treeNode = new TreeNodeImpl();
}
//
// implement tree node getters:
//
@Override
public ExtandedTreeNode getParent()
{
return parent;
}
@Override
public List<? extends ExtandedTreeNode> getChildren()
{
return children;
}
//
// implement tree node setters:
//
@Override
public void setParent(TreeNode parent)
{
this.parent = (ExtandedTreeNode) parent; // <--- How to avoid this type cast!!
}
@Override
public void addChild(TreeNode childNode)
{
children.add((ExtandedTreeNode) childNode); // <--- How to avoid this type cast!!
}
//
// implement basic operations by delegating to composite TreeNode:
//
public boolean isSelectable()
{
return treeNode.isSelectable();
}
// [...]
//
// implement additional operations:
//
@Override
public boolean isRemoveable()
{
return isRemoveable;
}
// [...]
}
Вопрос
Для меня иерархия типов отлично подходит для методов, доступных только для чтения и не для узлов дерева, но утечка для сеттеров setParent(..)
и addChild(..)
.В частности, рискованный тип ExtandedTreeNode
довольно злой, и я хочу от него избавиться.
Я думал об извлечении методов setParent(..)
и addChild(..)
к двум другим отдельным интерфейсам, таким как TreeNodeWriteable
и ExtandedTreeNodeWriteable
, но, возможно, есть и более лучшие дизайнерские решения.
Кто-нибудь знает шаблон проектирования или чертеж, который мог бы решить мою проблему с записывающими сеттер-узлами, специфичными для узлов дерева?