【问题标题】:How to avoid the duplication of code in this case?这种情况下如何避免代码重复?
【发布时间】:2013-04-10 16:31:59
【问题描述】:

我的项目是关于在 java 中实现一个超图

我的 hyperGraph 包含各种类型的 hyperEdge,具体取决于我拥有的顶点类型

顶点类型:图像,标签...

HyperEdge =Homogeneous(相同类型的相关顶点)/Heterogeneous(不同类型的相关顶点)

同构HyperEdge=图像-图像HyperEdge/标签-标签hyperEdge

这是一个快速绘制的UML图

这是我的代码

public interface HomogenousHyperedge< T extends Vertex<L>, L> extends Hyperedge {

   public abstract List<T> searchNearstNeighborsVertex(
      Hypergraph hypergraph, T vertex);
}


public class ImageImageHyperedge implements
   HomogenousHyperedge<ImageVertex, Map<String,Instance>> {

   @Override
   public List<ImageVertex> searchNearstNeighborsVertex(Hypergraph hypergraph,
        ImageVertex vertex) {
      return null;
   }
}

问题出在 ImageImageHyperEdge 类中我应该知道基于它的特征类型是什么我将搜索 ImageVertex 最近的邻居 我无法将它传递给超级接口的抽象方法,因为 TagTagHyperEdge 类不需要它

如果我用 {featureOneHyperEdge class ,...featureFiveHyperEdge class } 替换 ImageImageHyperEdge 类(我知道特征类型) 这将是重复的代码,因为它是相同的最近邻搜索算法


feature= 图像的低级特征(例如颜色直方图)
我有 5 种低级功能
我将使用每一个来搜索我当前图像的最近邻居
所有功能都存储在一个简单的文本文件中
相同的算法用于搜索最近的邻居
每次只更改文件

【问题讨论】:

  • 我不确定我是否正确理解了您的需求,所以这可能是两种方式。你能有一个基类 BaseFeatureHyperEdge 来实现搜索算法。并公开某种模板方法,该方法将被 FeatureOneHyperEdge、FeatureTwoHyperEdge 等覆盖。此模板方法应仅提供搜索所基于的特征类型。希望有帮助吗?
  • @DenisRosca 我得到的第一个想法是使用策略模式,我认为它类似于模板模式,你能解释一下你的想法吗?
  • 我想我会添加一个答案

标签: java oop inheritance interface


【解决方案1】:

您的 UML 设计不够好。跳过丑陋且难以阅读的“样式”,向我们展示“顶点”和“边缘”,以及关联图;不是您(可能过于复杂)的继承观念。

您的 API、设计和基本问题不是很清楚。 'Hyperedge' 类可以表示 Edge 的单个实例,并将其两端关联起来;或者它们可以(如果更好地命名)表示边缘类型,并从指定的端点参数全局搜索图形。

这些是完全不同的设计,在您弄清楚以上内容之前,您的问题毫无意义。

无论哪种方式,Edge.search() 都没有正确的签名。其中 VS 和 VE 是开始和结束顶点类型,而 TE 是边类型,它应该是:

public class EdgeType {
    public List<EV> getEndpoints (SV startVertex);
}

public class Vertex {
    public List<TE> Vertex.getEdges();
}
public class Edge {
    public EV Edge.getEndpoint();
}

最近邻算法应该使用泛型类型实现,然后由具体类根据需要(使用精确的类型签名)调用。

顺便说一句,当您提到“最近的邻居”时;也不清楚“最近邻”是指直接连接的顶点,这是微不足道的,还是要找到最近的远距离(如何测量距离?你没有指定)指定类型的顶点。

无论哪种方式,实现“Edge”子类型的实用性和正确性/需要似乎都不清楚。许多图形算法发现顶点/节点很有趣,并且对它们进行子类型化,但我不太了解导致这些的边的子类型化(或子类型化的实用性)。

最后提示:放弃复杂的命名,KISS。 “顶点”和“边缘”将帮助您获得清晰、简单、可理解和正确的设计。把多余的词留到之后你已经明白了。


响应 Nawara 提供的更多信息:

然后它是您建模的 EdgeType,当询问“最近的邻居”时,您应该使用 Start Vertex 并返回 Edge(如果您需要距离指标)或 Vertices。

对“Graph”的引用应该是 Vertex 参数中隐含的。

就您的 EdgeType 继承层次结构而言:应定义子类型和继承以遵循行为特征,而不是它们引用的泛型类型(顶点类型)。 OO 类层次结构设计的原则是建模,而不是存在

在这方面,您可能有一个 KnnDistanceEdgeType 和 FlickrDistanceEdgeType 类,作为祖先,或者,如果没有其他方法行为需要不同,作为实际的实现类。他们正在搜索的特征类型/类可以设置为属性——具有不同的属性和泛化,以响应不同的顶点类型。

例如。

IMAGE_IMAGE_EDGES = new KnnDistanceEdgeType<ImageVertex,ImageVertex>( ImageVertex.class, ImageVertex.class);
TAG_TAG_EDGES = new FlickrDistanceEdgeType<TagVertex,TagVertex>( TagVertex.class, TagVertex.class);
ANY_EDGES = new KnnDistanceEdgeType<Vertex,Vertex>( Vertex.class, Vertex.class);

如果在 EdgeType 中有很多其他行为(我们没有定义任何行为,并且无法想象太多),您可以将 KNN 和 Flickr 距离算法移到单独的类中。可能不需要。

记住:在 OO 中,子类是为了行为,而不是为了存在。并给我 +1 票!

【讨论】:

  • 我有一个复杂的超图 G=(V,E) ,V 是顶点集,它可能包含不同类型的顶点(图像、标签、位置...),而 E 是超边缘集,其中还包含不同的边缘类型(边缘之间的图像,标签之间,图像和标签之间)查找每个 hyperEdge 的入射顶点的方式根据 hyperEdge 类型而有所不同,例如在 hyperEdge 的起点和终点是我使用的图像顶点的情况下在 hypeEdge 的起点和终点是标签的情况下,knn 算法(使用欧几里得距离)我使用 Flickr 距离
  • 这就是为什么我认为我应该使用抽象类hyperedge 并从它继承多个子类,每个子类代表不同的 hyperEdge 类型
  • 在这种情况下,它是一个 EdgeKind 或 EdgeType -- 你要求它指定一个 StartVertex,并回答一个 Edge 或 Vertex 作为结果;如果需要距离,则边缘,如果不需要,则为顶点。
  • 这里有一个误解,我不是说edgeType是否是定向的,我的意思是EdgeKind ----------------确实是一个hyperEdge连接更多不是一个顶点,这是与 simlpe 图的主要区别
【解决方案2】:

根据您写的关于“功能”的内容,我会说这适合作为 ImageImageHyperEdge 类中的一个字段。您可以使用将定义它的任何各种成员来创建 FeatureType 类。

public class ImageImageHyperedge implements
   HomogenousHyperedge<ImageVertex, Map<String,Instance>> {

   private FeatureType featureType;

   @Override
   public List<ImageVertex> searchNearstNeighborsVertex(Hypergraph hypergraph,
        ImageVertex vertex) {
      return null;
   }
}

【讨论】:

  • 特征子类将继承具体实现,但它如何知道特征类型?
  • 类本身不会指示特征类型吗?如在,FeatureOneHyperEdge 不会表明特征类型是“FeatureOne”吗?
  • 是的,但是超类中的具体实现如何知道呢?
  • 我想我并没有完全遵循您的问题上下文中的“功能”是什么......如果您在问题中澄清这一点可能会有所帮助。
【解决方案3】:

试试这样的?

public abstract class BaseFeatureHyperEdge {

    @Override
   public List<ImageVertex> searchNearstNeighborsVertex(Hypergraph hypergraph,
        ImageVertex vertex) {   
      // implement nearest neighbor search algorithm
      // and call getFeatureType where you need it.
      // This will allow you to have the search algorithm only in one place. 
      //But make the search based on the feature type;
   }

   protected FeatureType getFeatureType();
}

public class FeatureOneHyperEdge extends BaseFeatureHyperEdge{

    @Override
    protected FeatureType getFeatureType() {
        return new FeatureTypeOne();
    }
}


public class FeatureTwoHyperEdge extends BaseFeatureHyperEdge{

    @Override
    protected FeatureType getFeatureType() {
        return new FeatureTypeTwo();
    }
}

也许你可以试试Template Method Pattern

【讨论】:

    猜你喜欢
    • 2020-11-23
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多