【问题标题】:Java: Object Oriented Design; LinkedList and StackJava:面向对象设计;链表和栈
【发布时间】:2011-04-20 13:12:36
【问题描述】:

我正在用 Java 编写 BFS 和 DFS。我希望做的是创建一个这样的类:

/** Preforms BFS and DFS on ...
*/
public class Search{


  private XXX toSearch;
  // where XXX is an interface of Stack and LinkedList that has
  // remove() and add() methods.  

  public Search(boolean isBFS){
    if(isBFS)
      toSearch = new LinkedList();
    else
      toSearch = new Stack();
  }

  public void preformSearch(){
    while(toSearch.size() > 0){
      preformSearchOn(toSearch.remove());  // <----- KEY LINE
    }
  }

  private void preformSearchOn(...){...}

}

这个类可以根据它的初始化方式执行 BFS 和 DFS。什么是XXX?我不认为它存在。

我认为面向对象编程的全部意义在于能够做这样很酷的事情。

处理这个问题的最干净的方法是什么?

【问题讨论】:

  • “执行”,而不是“预制”

标签: java list oop stack


【解决方案1】:

我认为您正在寻找Strategy pattern。这样做的方法不是 Java 特定的,也不是其他“很酷的东西”。这些类型的东西超越语言。

更具体地说,开发另外两个名为 BfsStrategy 和 DfsStrategy 的类。要求每个类实现一定的 Strategy 接口。使用您发布的类透明地对它们执行操作。 (如果需要,将类/接口名称更改为更合适。)

例如:

public final class Seeker<E, K> {

    private final E structure;
    private final SearchStrategy strategy;

    public Seeker(final E aStructure, final SearchStrategy aStrategy) {
        structure = aStructure;
        strategy = aStrategy;
    }

    public boolean search(K aKey) {
        return strategy.search(structure, key); //Pretty generic.
    }

}

【讨论】:

  • 好的,这很酷。我希望有比这更好的东西,但是……好吧。
  • 策略模式的一个很好的用法是“不错”。它的清晰性和可维护性非常漂亮。
【解决方案2】:

就广度优先和深度优先搜索而言,统一两者的一种方法是为每个搜索编写 java.util.Iterator 实现。让它成为你统一的抽象;它已经是 JDK 的一部分。

【讨论】:

    【解决方案3】:

    常用接口是java.util.Queue

    作为先进先出队列,您可以使用(例如)java.util.LinkedListjava.util.ArrayDeque

    作为后进先出队列,您可以使用 java.util.Collections.asLifoQueue 包装任何 Deque。

    堆栈以及超类 Vector 已被弃用,因为它同步所有方法访问,这通常是不必要的。我怀疑这就是它没有实现队列的原因。

    【讨论】:

      【解决方案4】:

      XXX 应该是 java.util.AbstractList 类型,因为 LinkedListStack 都是从它派生的。

      但这并不能解决您的问题,因为每个类的 remove() 方法的行为方式都相同。为了获得不同的行为,您实际上需要调用不同的删除方法:remove()pop()。作为方法,这些 remove() 和 pop() 都在 java.util.Linkedlist 上实现(参见Queue 接口),无需使用 java .util.Stack 类。

      您可以在 if 语句中调用不同的方法 pop()remove(),但这肯定是一个面向对象的反模式。一个基本的 OO 解决方案是实现 3 个类:

      • 名为Search类的抽象父类
      • BfsSearch:在搜索中使用 remove()。
      • DfsSearch:在搜索中使用 pop()。

      这样,该类的用户可以使用Search,而无需知道他使用的是BfsSearch 还是DfsSearch。

      更高级和更灵活的 OO 方法是使用 mike 所述的Strategy pattern。但是对于不需要这种灵活性的简单解决方案来说,这可能是矫枉过正。

      顺便说一句,一本关于 OO 设计的优秀书籍将解释所有这些类型的选择和模式是Larman

      Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition)

      【讨论】:

        猜你喜欢
        • 2016-01-19
        • 2012-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多