有没有特定的方法可以为某个子类提供某些超类的功能?

时间:2019-07-03 14:20:41

标签: java inheritance design-patterns polymorphism

问题

我正在尝试创建一个对象类可以实现某些功能的应用程序 可用操作总池中的操作。最终目标是不重复任何代码,并尽可能遵守OOP的法律。

更详细地讲,我正在尝试使用Lucene创建一个搜索引擎。露西恩
使用许多索引。我已经实现了一个简单的结构,其中不同的索引对象继承了父类的方法。问题是,无论在该父类中实现什么方法,它都会自动变为可供所有子类使用。我想让用户选择该选项,以确定他是否要进行短语搜索,术语搜索或特定索引可用的任何其他操作。问题是,例如某些索引不应具有进行短语搜索的选项。

最初的想法

我已经考虑过实现类似于 Composite 模式的内容,
如GoF所述。我会将搜索操作(例如术语搜索,词组搜索)实现为实现某些 Component 类的原始操作,然后将这些原始对象添加到 Composite 对象中。 Composite 对象将实现与原始对象相同的 Component 类。

public abstract class Index {
    public Index(String indexPath) {
        // Constructor using the information provided by the subclass
    }

    public void phraseSearch(...) {
         // Do the operation
    }

    public void termSearch(...) {
        // Do the operation
    }

    public void categorySearch(...) {
        // Do the operation
    }
}

public class ReviewIndex extends Index {
    public ReviewIndex() {
        super("./review_index/");
    }
}

public class TipIndex extends Index {
    public TipIndex() {
        super("./tip_index/");
    }
}

预期结果

ReviewIndex不能执行categorySearch而是应该
能够执行phraseSearch和termSearch。分别是TipIndex
应该能够执行某些父类方法。

最终思想

我知道我的解决方案中没有代码重复,但是有 每次创建新索引对象时都会生成无用的方法。 预先谢谢大家!

P.S。如果您认为 Composite 模式是可行的方式,那么您将以哪种方式将原始对象实际添加到Composite类中,并在需要时以哪种方式调用它们?

3 个答案:

答案 0 :(得分:1)

如果您不想为categorySearch(...)类使用ReviewIndex,请在保留categorySearch(...)方法的地方再创建一个层次结构。

示例:

public abstract class Index {
    public Index(String indexPath) {
        // Constructor using the information provided by the subclass
    }

    public void phraseSearch(...) {
         // Do the operation
    }
}

// Give a meaningful Name
public abstract class IndexChild1 extends Index {
    public void categorySearch(...) {
        // Do the operation
    }
}

// Give a meaningful Name 
public abstract class IndexChild2 extends Index {
     public void termSearch(...) {
            // Do the operation
     }
}

public class ReviewIndex extends IndexChild1 {
    public ReviewIndex() {
        super("./review_index/");
    }
}

public class TipIndex extends IndexChild2 {
    public TipIndex() {
        super("./review_index/");
    }
}

答案 1 :(得分:1)

在超类中定义的所有方法在派生类中都可用,但是使用Java 8,您可以通过在接口中使用默认方法来获得类似的信息。因此,代替一个包含所有可能方法的抽象类,您可以实现四个接口

public interface Searchable {
    public String getIndexPath();
}

public interface PhraseSearchable extends Searchable {
    public default void phraseSearch() {
        String indexPath = getIndexPath();
        // do the search
    }
}

public interface TermSearchable extends Searchable {
    public default void termSearch() {
        String indexPath = getIndexPath();
        // do the search
    }
}

public interface CategorySearchable extends Searchable {
    public default void categorySearch() {
        String indexPath = getIndexPath();
        // do the search
    }
}

为避免重复的代码,您可以创建一个抽象类

public abstract class AbstractSearchable implements Searchable {
    private String indexPath;

    public AbstractSearchable(String indexPath) {
        this.indexPath = indexPath;
    }

    // other methods that might be useful
}

然后您的实际类可以实现相应的接口

public class ReviewIndex extends AbstractSearchable implements CategorySearchable {
    public ReviewIndex() {
        super("./review_index/");
    }
}
public class TipIndex extends AbstractSearchable implements PhraseSearchable, TermSearchable {
    public ReviewIndex() {
        super("./review_index/");
    }
}

是否可能在很大程度上取决于搜索方法的实际实现。接口不能包含任何成员等,因此这些方法必须能够自行运行(就像静态方法,而无需使用类的任何静态成员)。您可以通过在Searchable接口中添加更多方法来解决此问题,这些方法提供数据并在抽象类中执行实现,但是由于接口中所有已声明的方法都是公共的,因此可能会将内部内容公开给公众。

答案 2 :(得分:0)

如果需要具有相同的对象并根据需要在ReviewIndex和TipIndex类中使用它们,则可以使用Composite模式。您可以使用一个表示聚合的列表,并且可以按任意顺序对每个对象(PhraseSeach,TermSearch,CategorySearch)使用一个实例化。 这是代码:

import java.util.ArrayList;
import java.util.List;


public class Main{

    public static void main(String[] args) {
        Main m = new Main();
        m.run();


    }

    public void run() {
        ReviewIndex ri = new ReviewIndex();
    }


    public interface ISearch {
        public void search();
    }

    public class SearchComposite implements ISearch{

        private List<ISearch> l = new ArrayList<ISearch>();

        public SearchComposite(String index) {
            System.out.println(index);
        }

        public int addSearch(ISearch search) {
            l.add(search);
            return this.l.size() - 1;
        }

        public List<ISearch> getSearch(){
            return this.l;
        }

        public void search() {
            System.out.println("search");
        }
    }

    public class CategorySearch implements ISearch{
        @Override
        public void search() {
            System.out.println("category search");
        }
    }

    public class PhraseSearch implements ISearch{
        @Override
        public void search() {
            System.out.println("phrase search");
        }
    }

    public class TermSearch implements ISearch{
        @Override
        public void search() {
            System.out.println("term search");
        }
    }



    CategorySearch cs = new CategorySearch();
    TermSearch ts = new TermSearch();
    PhraseSearch ps = new PhraseSearch();


    public class ReviewIndex {
        SearchComposite sc = new SearchComposite("./review_index/");
        public ReviewIndex() {
            int p = sc.addSearch(ps);
            int t = sc.addSearch(ts);
            sc.search();
            List<ISearch> s = sc.getSearch();
            s.get(p).search();
            s.get(t).search();
        }
    }

    public class TipIndex {

        SearchComposite sc = new SearchComposite("./tip_index/");
        public TipIndex() {
            int p = sc.addSearch(ps);
            int t = sc.addSearch(ts);
            int c = sc.addSearch(cs);
            sc.search();
            List<ISearch> s = sc.getSearch();
            s.get(p).search();
            s.get(t).search();
            s.get(c).search();
        }
    }
}

上面的代码输出为:

./review_index/
search
phrase search
term search

并且我们对ReviewIndex和TipIndex类使用了相同的CategorySearch,TermSearch和PhraseSearch。