Выведите производные типы полиморфно - PullRequest
0 голосов
/ 17 декабря 2018

Каков рекомендуемый подход к проектированию / альтернатива ситуации ниже:

BaseCalculator:
BaseType prepareData()
useData(BaseType)

Производные калькуляторы используют производный тип для переопределения базовой функциональности -

DerivedCalculator1:
BaseType prepareData(){ return DerivedType1}
useData(BaseType t1){ DerivedType1 t=(DerivedType1)t1 //typecast  down and proceed....}

DerivedCalculator2
BaseType prepareData(){ return DerivedType2}
useData(BaseType t1){ DerivedType2 t=(DerivedType2)t1 //typecast down and proceed....}

Существует ли подход к проектированию, которого следует избегатьприведение типов производными классами - как всегда оставить ворота открытыми для неудачи во время выполнения?

1 Ответ

0 голосов
/ 04 января 2019

Одной альтернативой является перемещение полиморфного поведения в реализации BaseType, а не в реализации BaseCalculator.Например:

public interface BaseType {
    public void process(Calculator calc);
}

public class DerivedType1 implements BaseType {

    @Override
    public void process(Calculator calc) {
        // Do something specific to derived type 1
    }
}

public class DerivedType2 implements BaseType {

    @Override
    public void process(Calculator calc) {
        // Do something specific to derived type 2
    }
}

public class Calculator {

    public void doSomething(BaseType bt) {
        bt.process(this);
    }
}

Если такого типа решения недостаточно, более сложным решением является Шаблон посетителя .Шаблон посетителя позволяет обрабатывать любой произвольный объект BaseType любым произвольным BaseCalculator с использованием double-dispatch .Уловка в том, что все реализации BaseCalculator должны иметь метод для обработки каждой из реализаций BaseType.Например:

public interface BaseType {
    public void process(Calculator calc);
}

public class DerivedType1 implements BaseType {

    @Override
    public void process(Calculator calc) {
        // Do something specific to derived type 1
    }
}

public class DerivedType2 implements BaseType {

    @Override
    public void process(Calculator calc) {
        // Do something specific to derived type 2
    }
}

public interface BaseCalculator {
    public void handle(DerivedType1 dt);
    public void handle(DerivedType2 dt);
}

public class DerviedCalculator1 implements BaseCalculator {

    @Override
    public void handle(DerivedType1 dt) {
        dt.process(this);
    }

    @Override
    public void handle(DerivedType2 dt) {
        dt.process(this);
    }
}

public class DerviedCalculator2 implements BaseCalculator {

    @Override
    public void handle(DerivedType1 dt) {
        dt.process(this);
    }

    @Override
    public void handle(DerivedType2 dt) {
        dt.process(this);
    }
}
...