0

У меня есть интерфейс MyInterface и конкретная реализация MyImplementation, которая реализует интерфейс. Теперь мне нужно создать несколько «Wrappers», которые также должны реализовать MyInterface и будут обертывать оригинальный объект MyImplementation. Обертка в некотором смысле, что свойства и методы функций на обертке будут служить своего рода Proxy - т. Е. Выполняя некоторые проверки входных данных и передавая их исходной реализации MyImplementation. Мне нужно уложить несколько оберток друг в друга, то есть иметь MyValidator1, MyValidator2 и т. Д., Которые могут быть - в зависимости от варианта использования - все добавлены к одному объекту.Несколько оберток объектов в TypeScript/JavaScript

Некоторые код, чтобы сделать вещи яснее:

interface MyInterface { 
    method1(arg1, arg2): any; 
} 

class MyImplementation implements MyInterface { 
    method1(arg1, arg2) { 
     /* perform checks and or throw */ 
    } 
} 

class MyValidator1 implements MyInterface { 
    method1(arg1, arg2) { 
     /* ... */ 
    } 
} 

class MyValidator2 implements MyInterface { 
    method1(arg1, arg2) { 
     /* ... */ 
    } 
} 

let o1 = new MyImplementation(); 
// only apply validator1 
AddValidator1(o1); 

let o2 = new MyImplementation(); 
// only apply validator2 
AddValidator2(o2); 

let o3 = new MyImplementation(); 
// apply both validators 
AddValidator1(o3); 
AddValidator2(o3); 

// intended call hierarchicy when calling o3.method1(arg1, arg2) 
// MyValidator1.method1(arg1, arg2) 
// MyValidator2.method1(arg1, arg2) 
// MyImplemenation.method1(arg1, arg2) 
// but the order of the validators is not important! 

Это просто какой-то код предложение, я ищу для всех видов моделей, которые могут отличаться от приведенного выше кода для достижения этой цели.

Важно, чтобы все экземпляры объектов были инкапсулированы - они должны вести себя так, как если бы они были MyImplemenation потребителю. Валидаторы должны добавлять частные функции или свойства.

Каков наилучший способ для этого? Может быть, изменить прототип во время выполнения?

+0

Вы добавляете валидаторы в экземпляр каждого класса? Кроме того, существует ли только один экземпляр для валидатора? –

+0

похоже, что вы ищете нечто похожее на черту. Может быть, смешение поможет? – toskv

+0

Идея состоит в том, чтобы иметь возможность смешивать и сопоставлять валидаторы. Нужно иметь возможность добавлять какие-либо валидаторы в реализацию, без какого-либо валидатора, знающего о другом. – Dyna

ответ

0

Я не знаю, машинопись, но вот как это будет сделано в обычном Javascript (синтаксис ES6):

class MyInterface { 
    foo() { 
    throw new Error('To be implemented'); 
    } 
} 

class MyImplementation extends MyInterface { 
    foo() { 
    return 42; 
    } 
} 

function wrapWithValidator1(impl) { 
    class MyValidator1 extends MyInterface { 
    constructor() { 
     for (const key of Object.keys(impl)) { 
     this[key] = impl[key]; 
     } 
    } 

    foo() { 
     validateStuff(); 
     return impl.foo(); 
    } 
    } 

    return new MyValidator1(); 
} 

function wrapWithValidator2(impl) { 
    class MyValidator2 extends MyInterface { 
    constructor() { 
     for (const key of Object.keys(impl)) { 
     this[key] = impl[key]; 
     } 
    } 

    foo() { 
     validateOtherStuff(); 
     return impl.foo(); 
    } 
    } 

    return new MyValidator2(); 
} 

Ваши валидаторы являются обертками над реализацией, потому что они «расширить» его. Они наследуют от прототипа реализации (и, следовательно, все его свойства/методы), но они могут переопределить существующий метод для обеспечения дополнительного поведения.

Используйте super.myMethod(), когда вы переопределяете метод вызова родительского метода.

+0

Это не работает. Если вы хотите, чтобы валидатор1 и валидатор2 в одном экземпляре, нужно получить от другого, но валидаторы не должны знать друг о друге, они знают интерфейс только. – Dyna

+0

Хорошо, я думаю, что понял. Я отредактировал свой ответ. Вам необходимо динамически создавать классы валидатора, так как им нужно закрыть реализацию, которую вы хотите во время выполнения. –

+0

Поэтому, если вы хотите как Val1, так и Val2, вам просто нужно вызвать обе функции в строке: 'wrapWithValidator2 (wrapWithValidator1 (myImpl))' –

0

Как насчет наличия списка валидаторов в классе MyImplementation?
Что-то вроде:

abstract class Validator implements MyInterface { 
    abstract method1(arg1, arg2): any; 
} 

class MyValidator1 extends Validator { 
    method1(arg1, arg2) { 
     /* ... */ 
    } 
} 

class MyValidator2 extends Validator { 
    method1(arg1, arg2) { 
     /* ... */ 
    } 
} 

class MyImplementation implements MyInterface { 
    private validators: Validator[]; 

    constructor() { 
     this.validators = []; 
    } 

    addValidator(validator: Validator) { 
     this.validators.push(validator); 
    } 

    method1(arg1, arg2) { 
     this.validators.every(validator => { /* do something here */ return false; }); 
     /* perform checks and or throw */ 
    } 
} 

(code in playground)

+0

Невозможно, так как класс 'MyImplemenation' должен знать о vlaidators. Он должен знать только интерфейс, так как валидаторы должны быть доступны сторонними сторонами. – Dyna

+1

Хорошо, тогда сделайте 'Validator' интерфейсом вместо класса, но идея такая же –

Смежные вопросы