Eu tenho uma classe: A
que é um composto de um número de classes menores, B
, C
e D
.
B
, C
, E D
implementar as interfaces IB
, IC
e, ID
respectivamente.
Uma vez que A
suporta todas as funcionalidades de B
, C
e D
, A
implementa IB
, IC
e ID
também, mas isso infelizmente leva a muito redirecionamento na implementação deA
Igual a:
interface IB
{
int Foo {get;}
}
public class B : IB
{
public int Foo {get {return 5;}}
}
interface IC
{
void Bar();
}
public class C : IC
{
public void Bar()
{
}
}
interface ID
{
string Bash{get; set;}
}
public class D: ID
{
public string Bash {get;set;}
}
class A : IB, IC, ID
{
private B b = new B();
private C c = new C();
private D d = new D();
public int Foo {get {return b.Foo}}
public A(string bash)
{
Bash = bash;
}
public void Bar()
{
c.Bar();
}
public string Bash
{
get {return d.Bash;}
set {d.Bash = value;}
}
}
Existe uma maneira de se livrar desse redirecionamento padrão A
? B
, C
E D
toda a implementar a funcionalidade diferente, mas comum, e eu gosto disso A
implementos IB
, IC
e ID
porque isso significa que eu posso passar em A
si como uma dependência combinando essas interfaces, e não tem que expor os métodos auxiliares internos.
c#
design-patterns
patterns-and-practices
composition
Nick Udell
fonte
fonte
A
implementarIB
,IC
eID
é mais sensato escrever doPerson.Walk()
quePerson.WalkHelper.Walk()
por exemplo.Respostas:
O que você está procurando é chamado de mixins . Infelizmente, o C # não suporta nativamente esses.
Existem poucas soluções alternativas: uma , duas , três e muito mais.
Na verdade, eu realmente gosto do último. A ideia de usar a classe parcial gerada automaticamente para gerar o padrão é provavelmente a mais próxima possível da solução realmente boa:
fonte
Embora não reduza o padrão no próprio código, o Visual Studio 2015 agora vem com uma opção de refatoração para gerar automaticamente o padrão para você.
Para usar isso, primeiro crie sua interface
IExample
e implementaçãoExample
. Em seguida, crie sua nova classeComposite
e torne-a herdadaIExample
, mas não implemente a interface.Adicione uma propriedade ou campo do tipo
Example
à suaComposite
classe, abra o menu de ações rápidas no tokenIExample
no seuComposite
arquivo de classe e selecione "Implementar interface através de 'Exemplo'", onde 'Exemplo' neste caso é o nome do campo ou propriedade.Observe que, embora o Visual Studio gere e redirecione todos os métodos e propriedades definidos na interface para essa classe auxiliar, você não redirecionará eventos a partir do momento em que essa resposta foi postada.
fonte
Sua turma está fazendo muito, é por isso que você tem que implementar tanto clichê. Você diz nos comentários:
Discordo. É provável que o ato de andar envolva muitas regras e não pertença à
Person
classe - ele pertence a umaWalkingService
classe com umwalk(IWalkable)
método no qual Person implementaIWalkable
.Lembre-se sempre dos princípios do SOLID ao escrever código. Os dois que são mais aplicáveis aqui são Separação de preocupações (extrair o código ambulante para uma classe separada) e Segregação de interface (dividir interfaces em tarefas / funções / habilidades específicas). Parece que você pode ter um pouco do I com suas múltiplas interfaces, mas está desfazendo todo o seu bom trabalho, fazendo uma classe implementá-las.
fonte
walk(IWalkable)
método, eu pessoalmente não gosto, porque os serviços de caminhada se tornam responsabilidade do chamador, e não da Pessoa, e a consistência não é garantida. Qualquer pessoa que chama deve saber qual serviço usar para garantir consistência, enquanto mantê-lo na classe Person significa que ele deve ser alterado manualmente para que o comportamento da caminhada seja diferente, enquanto ainda permite a inversão de dependência.O que você está procurando é herança múltipla. No entanto, nem C # nem Java possuem.
Você pode estender B de A. Isso eliminará a necessidade de um campo privado para B, bem como a cola de redirecionamento. Mas você só pode fazer isso para um de B, C ou D.
Agora, se você pode fazer C herdar de B e D de C, você só precisa ter A estender D ...;) - só para deixar claro, porém, não estou incentivando isso neste exemplo, pois não há indicação por isso.
Em C ++, você seria capaz de herdar A de B, C e D.
Mas a herança múltipla dificulta a discussão dos programas e tem seus próprios problemas; Além disso, geralmente há uma maneira limpa de evitá-lo. Ainda assim, às vezes sem ele, é preciso fazer trocas de design entre o padrão repetitivo e como o modelo de objetos é exposto.
Parece que você está tentando misturar composição e herança. Se fosse C ++, você poderia usar uma solução pura de herança. Mas como não é, eu recomendo adotar a composição.
fonte