Não consigo descobrir uma solução melhor para o meu problema. Eu tenho um controlador de exibição que apresenta uma lista de elementos. Esses elementos são modelos que podem ser uma instância de B, C, D, etc e herdar de A. Portanto, nesse controlador de exibição, cada item deve ir para uma tela diferente do aplicativo e passar alguns dados quando o usuário seleciona um deles . As duas alternativas que me vêm à cabeça são (ignore a sintaxe, não é um idioma específico)
1) interruptor (eu sei que é uma porcaria)
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
switch(a.type) {
case b:
B b = (B)a;
go to screen X;
x.v1 = b.v1; // fill X with b data
x.v2 = b.v2;
case c:
go to screen Y;
etc...
}
}
2) polimorfismo
//inside the view controller
void onClickItem(int index) {
A a = items.get(index);
Screen s = new (a.getDestinationScreen()); //ignore the syntax
s.v1 = a.v1; // fill s with information about A
s.v2 = a.v2;
show(s);
}
//inside B
Class getDestinationScreen(void) {
return Class(X);
}
//inside C
Class getDestinationScreen(void) {
return Class(Y);
}
Meu problema com a solução 2 é que, como B, C, D, etc. são modelos, eles não devem saber sobre coisas relacionadas à exibição. Ou deveriam, nesse caso?
fonte
Mais um comentário do que uma resposta, mas acho que é uma brincadeira. Ou o View tem de saber tudo sobre o modelo para que ele possa escolher a tela (switch) ou o modelo tem de saber tudo sobre a vista de modo que pode escolher a tela (polimorfismo). Eu acho que você tem que escolher o que você acha que será o mais simples ao longo do tempo; não há certo resposta para a pergunta. (Espero que alguém possa me provar errado.) Eu mesmo me inclino ao polimorfismo.
Eu topo um pouco com esse problema. O caso mais irritante foi uma classe Wanderer, cujas instâncias vagavam por um mapa. Para desenhá-lo, o monitor precisava saber sobre o Wanderer ou o Wanderer precisava saber sobre o monitor. O problema era que havia duas telas (com mais aparecendo). Como o número de diferentes subclasses Wanderer era grande e crescente, coloquei o código de desenho nas subclasses Wanderer. Isso significava que cada classe grande tinha exatamente um método que precisava saber sobre Graphics2D e exatamente um método que precisava saber sobre Java3D. Feio.
Acabei dividindo a classe, dando-me duas estruturas de classes paralelas. A classe Wanderer ficou livre de conhecer os gráficos, mas a classe DrawWanderer ainda precisava saber mais sobre o Wanderer do que era decente e precisava conhecer dois (e talvez mais) ambientes gráficos completamente diferentes (Views). (Suponho que essa ideia de dividir a classe possa ser uma resposta, mas tudo o que realmente faz é conter um pouco o problema.)
Eu acho que esse é um problema muito geral e fundamental do design orientado a objetos.
fonte
Eu acho que ir com o switch é uma opção melhor do que ir com o polimorfismo para este caso.
É uma coisa bastante simples de se fazer, então não acho que tenha que ser complicado demais pelo uso de polimorfismo.
Eu gostaria de cunhar nesta postagem do blog . As instruções de troca não são necessariamente feias, desde que você as use corretamente. E no seu caso, abstrair modelos como o para uso em um controlador pode ser um exagero e gerar resultados indesejados. Como violar o SRP.
fonte
Eu concordo com esta preocupação. Também estou um pouco preocupado que objetos que estão em uma caixa de combinação tenham comportamento. Não tenho certeza de que seja uma "coisa ruim" nunca ter feito isso, apenas parece uma escolha não natural para mim.
Além disso, não parece
A
e suas subclasses são do tipo com o qual você tem polimorfismo interessante. O tipo interessante é realmenteScreen
. Neste exemplo,A
é apenas uma classe que contém informações para informar aScreen
criação.Se você fizer com que a caixa de combinação contenha uma lista de quaisquer
a.type
retornos, uma instrução switch parece mais natural. No entanto, em vez de colocá-lo corretamente no manipulador de eventos click, eu o colocaria em aScreenFactory
. Então você tem:Isso permite testar o comportamento de criação da tela e extrai algumas funcionalidades da sua interface do usuário. Ele mantém as camadas da sua vista intactas. Talvez isso simplifique seu design, se isso significa que as
A
subclasses podem ser recolhidas natype
bandeira que elas contêm.fonte