Разработка интерфейса для методов с разными параметрами - PullRequest
1 голос
/ 10 июля 2011

Это скорее вопрос проектирования, чем вопрос графики, но здесь есть немного предыстории: я пишу программу, использующую OpenGL (на Java, с JOGL), которая может загружать сетку из файла .obj и отображать ее,Пока проблем нет, но мне нужно иметь возможность применить серию фильтров или преобразований к сетке, например,

  • Тесселяция граней
  • Добавление случайного шума в вершины
  • Применение алгоритма сглаживания к зашумленной сетке
  • Раскраска сетки (которая может основываться или не основываться как на сглаженной сетке, так и на исходной чистой сетке)

Несколькоиз этих фильтров будут применяться по порядку.Я также хочу предоставить какой-то согласованный интерфейс для других людей, чтобы они могли создавать свои собственные (возможно, общие) фильтры.Как бы я поступил об этом?

Основная проблема заключается в том, что для фильтров может потребоваться различный набор параметров, например, для одного алгоритма сглаживания может потребоваться выбор двух параметров пользователем (во время выполнения с использованием графического интерфейса пользователя),тогда как другой может не требовать ничего.Точно так же некоторые алгоритмы окраски могут требовать только сглаженную сетку и цвет RGB, другой может потребовать как сглаженную сетку, так и чистую сетку (из которой он генерирует цвета).Поэтому вызов может выглядеть следующим образом:

mesh = smoothingFilter1.filter(mesh, booleanParam);

, но он может быть совершенно другим:

mesh = smoothingFilter2.filter(mesh, intParam1, intParam2, floatParam);

Очевидно, мой код должен быть способен вызывать общий метод фильтрации.Было бы хорошей идеей определить абстрактный класс или интерфейс для Filter с нереализованным методом регистрации себя (и его обязательных параметров) с каким-то управляющим классом?Кажется довольно сложным, но я не могу придумать другого способа заставить программу работать с методом фильтра с произвольной сигнатурой.Я даже не уверен, что эта идея сработает ...

Существует ли шаблон проектирования для обработки ситуаций такого типа?

Ответы [ 3 ]

4 голосов
/ 10 июля 2011

На самом деле вам не нужны параметры вообще. Mesh filter(Mesh mesh); будет достаточно. Переместите другие параметры в конструктор различных конкретных реализаций фильтров.

выглядит примерно так:

Filter smoothingFilter1 = new FirstFilter(booleanParam);    
mesh = smoothingFilter1.filter(mesh);

Filter smoothingFilter2 = new SecondFilter( intParam1, intParam2, floatParam);    
mesh = smoothingFilter2.filter(mesh);

Для создания экземпляров вы можете использовать что-то вроде:

public interface AbstractFilterFactory {
  Params getRequiredParams();
  Filter createFilter(Params params);
}

public interface Params {
 // some interface that describes specific parameters that are required
 // probably a collection of Parameter classes which has name, type and value information. 
}

public class FirstFilterFactory implements AbstractFilterFactory {
  // return a concrete params object use that to instantiate a concrete filter.
}
1 голос
/ 10 июля 2011

Другое подобное решение, без обобщений, заключается в объявлении абстрактного класса параметров:

abstract class FilterParameters { }

Ваш интерфейс выглядит следующим образом:

interface Filter {
  Mesh filter(Mesh input, FilterParameters params);
}

Для каждого нового набора параметров, который требуется вамобъявите новый подкласс FilterParameters, который может содержать все необходимые параметры.

// Foo parameter only.
class FooFilterParameters extends FilterParameters { 
  public Foo getFoo() { }
  // Other stuff.
}

// Foo, Bar and int parameters.
class BarFilterParameters extends FilterParameters { 
  public Foo getFoo() { }
  public Bar getBar() { }
  public int getMagnification() { }
  // Other stuff.
}

Каждый метод фильтра должен проверять тип своего параметра:

// Foo filter
public Mesh filter(Mesh inMesh, FilterParameters fp) {
  if (!(fp instanceof FooFilterParameters)) {
    throw new IllegalParameterException("Not FooFilterParameters.");
  }
  // Foo filter code here.
}

rossum

1 голос
/ 10 июля 2011

Другой подход (который мне не очень нравится) состоит в объединении параметров в объекте и использовании полиморфизма для передачи различных параметров для различных объектов.

Во-первых, быстрая и грязная версия,используя карту:

interface Filter {
    Mesh filter(Mesh input, Map<String, Object> params);
}

Полиморфный объект:

abstract class Parameters {
}

interface Filter {
    Mesh filter(Mesh input, Parameters params);
}

class FirstFilterParameters extends Parameters {
    private boolean booleanParam;
    // constructor, getter, possibly setter
}

class FirstFilter implements Filter {
    Mesh filter(Mesh input, Parameters params) {
        FirstFilterParameters ffParams = (FirstFilterParameters)params;
        boolean booleanParam = ffParams.getBooleanParam();
        // etc
    }
}

Полиморфный объект с типовой безопасностью благодаря универсальным типам:

abstract class Parameters {
}

interface Filter<P extends Parameters> {
    Mesh filter(Mesh input, P params);
}

class FirstFilterParameters extends Parameters {
    private boolean booleanParam;
    // constructor, getter, possibly setter
}

class FirstFilter implements Filter<FirstFilterParameters> {
    Mesh filter(Mesh input, FirstFilterParameters params) {
        boolean booleanParam = params.getBooleanParam();
        // etc
    }
}

Версия с универсальными типами делает полиморфную обработкуФильтры сложнее, хотя.Что делать, если вы хотите иметь список фильтров и список параметров и применять каждый фильтр с соответствующими параметрами?Там нет никакого способа сделать это безопасно.Вам нужно будет выполнить какой-нибудь маневр, например, упаковав каждую пару в объект с собственным параметром типа, например FilterWithParams<P extends Parameters>, и имеющим List<FilterWithParams<?>>.В этот момент вы в основном заново изобрели решение М. Платвоета!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...