Не пытайтесь усложнить ситуацию по мере необходимости :-) Из названий, которые у вас есть в настоящее время, я бы не знал, как использовать эту функциональность. Что такое индексатор? Что такое препроцессор? Эти вещи могут быть чем угодно. Поэтому вместо этого сделайте это простым и с точки зрения предметной области прямо в точку (я приведу пример на TypeScript, чтобы вы могли видеть, какие типы используются и где):
Сначала мы определим доменные службы стоп-слов (наш бизнес-домен):
/** we'll use this to provide stop words as array of strings */
class StopWords {
public stopWords: string[] = [];
constructor(words?: string[]) { this.stopWords = words }
}
/** single responsibility of this class: actually remove the stopwords */
class StopWordsRemovalService {
/** inject stopwords through constructor */
constructor(stopWords: StopWords) {}
/** here we do the real removal work */
public removeAllStopWordsFrom(text: string): string { return ''; }
}
Теперь мы можем предоставить стоп-слова из любого места (подробнее об инфраструктуре):
/** TypeScript provids interfaces, which you don't have in plain JS. It merely
* defines the class method signatures, which is quite useful in software design */
interface StopWordsProvider {
getStopWords(): StopWords;
}
class DefaultStopWordsProvider implements StopWordsProvider {
getStopWords(): StopWords {
return new StopWords(['a', 'an']);
}
}
class DbStopWordsProvider implements StopWordsProvider {
getStopWords(): StopWords {
return db.query("SELECT stopWords FROM ...");
}
}
И, наконец, мы свяжемся вместе:
const swremoval: StopWordsRemovalService = new StopWordsRemovalService(new DefaultStopWordsProvider().getStopWords());
swremoval.removeAllStopWordsFrom('a sample text');
Чтобы связать все вместе, вы можете теперь использовать инфраструктуру внедрения зависимостей, такую как InversifyJS
Обновление: нам нужно будет возвращать разные стоп-слова по идентификатору пользователя.
Первый вопрос, который приходит мне в голову: насколько важен идентификатор пользователя для бизнеса? Если для определения стоп-слов требуется идентификатор пользователя , всегда , идентификатор пользователя является неотъемлемой частью нашего домена! Если для определения стоп-слов требуется идентификатор пользователя , иногда , он может не являться неотъемлемой частью нашего домена. Давайте рассмотрим два случая:
ИД пользователя всегда , необходимый для получения стоп-слов
Если идентификатор пользователя важен для домена и всегда требуется для определения стоп-слов, то давайте сделаем его частью договора:
/** TypeScript provids interfaces, which you don't have in plain JS. It merely
* defines the class method signatures, which is quite useful in software design */
interface StopWordsProvider {
/** Returns all the stop words for the given user */
getStopWords(userID: number): StopWords;
}
Теперь все классы, реализующие этот интерфейс, должны учитывать идентификатор пользователя.
Идентификатор пользователя иногда требуется для получения стоп-слов
Если идентификатор пользователя требуется только для некоторых поисков, мы не изменим контракт с стоп-словами (т. Е. Интерфейс)! Вместо этого мы предоставим UserSpecificStopWordsProvider
, который выполняет поиск. Для настройки идентификатора пользователя мы будем использовать фабричный шаблон:
/** The user-specific stopwords provider is configured through
* constructor-based injection */
class UserSpecificStopWordsProvider implements StopWordsProvider {
constructor(private userId: number) {}
getStopWords(): StopWords {
return db.query("SELECT * FROM sw WHERE userId = :userId", this.userId);
}
}
/** To simplify the usage, we'll provide a factory to do this. */
class UserSpecificStopWordsProviderFactory {
factoryProvider(userId: number): StopWordsProvider {
// potentially inject more dependencies here
return new UserSpecificStopWordsProvider(userId);
}
}
/** We can then use it as follows: */
const factory = new UserSpecificStopWordsProviderFactory();
factory.factoryProvider(5).getStopWords();