[Duvida] Padrões GRASP - Expert

Olá pessoal, estou com um exercício aqui do padrão Expert pra resolver, e estou com algumas dúvidas, gostaria de esclarecê-las.
Material Original: http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/pat/expert.htm

O problema é o seguinte:

Fita.java

public class Fita { 
    public enum Tipo { 
          normal, lancamento, infantil
    };

    private String titulo;
    private Tipo codigoDePreco;

   //Getters and Setters
}

Aluguel.java

public class Aluguel { 
    private Fita fita;
    private int diasAlugada;

   //Getters and Setters

}

Cliente.java

public class Cliente { 
    private String nome;
    private List<Aluguel> fitasAlugadas = new ArrayList<Aluguel>();

    public void adicionaAluguel(Aluguel aluguel) { 
         fitas.add(aluguel);
    } 


    public void extrato() { 
          double valorTotal = 0.0;

          //Responsabilidade 1: Calcula o total dos aluguéis
          for (Aluguel cadaAluguel : fitasAulagadas )
               double valorCorrente = 0.0
               
               //Responsabilidade 2: Calcula o valor de cada aluguel
               Tipo tipo = cadaAluguel.getFita().getCodigoDePreco();
               switch(tipo) {
                  case normal: 
                       //Responsabilidade 3: Calcular o preço de cada fita 
                       valorCorrente += 2;
                       
                       //Responsabilidade 4: Calcular multa
                       int dias = cadaAluguel.getDiasAlugada();
                       if (  dias > 2 ) { valorCorrente += (dias - 2) * 1.5; }
                       break;

                   case lancamento:
                       //Responsabilidade 3: Calcular o preço de cada fita
                       int dias = cadaAluguel.getDiasAlugada();
                       valorCorrente += dias * 3;
                       //Note que não há cálculo de multa para filmes lançamento
                       break;
                   case infantil: 
                       //Responsabilidade 3: Calcular o preço de cada fita 
                       valorCorrente += 1.5;
                       
                       //Responsabilidade 4: Calcular multa
                       int dias = cadaAluguel.getDiasAlugada();
                       if (  dias > 3 ) { valorCorrente += (dias - 3) * 1.5; }
                       break;
               }//switch
           }//for    
     }
}

Como vocês podem ver, identifiquei as principais responsabilidades que existem na classe Cliente. Preciso agora identificar onde essas responsabilidades devem estar concentradas, devem permanecer na classe Cliente? na classe Aluguel ou na classe Fita? Decidi, analisar uma por uma.

Responsabilidade 1 (getTotal()): - Para Calcular o total dos aluguéis É PRECISO conhecer todos aluguéis (Information Expert: Cliente)
BELEZA!

Responsabilidade 2 (getPrecoAluguel()): - Para Calcular o valor do aluguel É PRECISO ter acesso tanto ao preco da fita (getPrecoFita()) quanto ao preço da multa (getPrecoMulta()) . Pois o cálculo é getPrecoFita() + getPrecoMulta(). Nesse caso quem é o information expert, já que eu não sei quem é responsável por calcular o preço da fita e nem o valor da multa.

Responsabilidade 3 (getPrecoFita()): - Para Calcular o preço de cada fita É PRECISO ter acesso ao tipo da fita (Fita.codigoDePreco) e quantidade de dias alugada (Aluguel.diasAlugada), no caso de fitas lançamento o preço pago é 3 reais por dia. Nesse caso, quem é o information expert? Aluguel (porque encapsula uma fita, dessa forma posso fazer fita.getCodigoDePreco() para obter o tipo ) ? Ou a Fita é o information expert (porque a classe fita é responsável por conhecer seu preço… Alta coesão)

Responsabilidade 4 (getPrecoMulta()): - Para Calcular o valor da multa É PRECISO ter acesso a quantidade de dias que ela ficou alugada e também o tipo da fita(dependendo do tipo podemos passar 2 ou até 3 dias com a fita) . -> Aluguel.diasAlugada e Fita.codigoDePreco. A dúvida é a mesma da de cima.

O que eu quero chamar atenção é que: seguindo o princípio do Expert de: “Colocar as responsabilidades nas classes que detém a maioria das informações para cumprir suas responsabilidades” , muitas vezes nos permite uma dupla escolha. Nessas situações, devemos levar em conta os outros princípios GRASP: baixo acoplamento, alta coesão… ?

Ninguém? =/

Este é o mais complexo deles. Em aluguel não faz muito sentido, em Cliente a principio tambem nao faz. Este talvez fosse um caso de um service de calculo de totais de algueis.Ou seja, nenhum das suas Entities tem esta responsabilidade. Seria algo como:

serviceCalculadorDeAlgueis().calcularTotalDeLocacoesDoCliente(umCliente);

Só uma ideia, talvez alguem tenha algo melhor.

Este é responsabilidade de Aluguel na minha opiniao. No dia em que voce alugar uma fita, esta entidade tera que ser informada sobre a taxa corrente e preço da fita naquele dia. Ou seja, ela vai precisar de referencias as outras entidades do sistema, mas a responsabilidade do calculo é dela.

Aluguel de novo. A Fita é sim responsavel por conhecer seu preco, mas não é responsavel por saber quantos dias ficara alugada para um cliente. Novamente responsabilidade de Aluguel, pois ela sabe de qual fita estamos falando e pode lhe pedir rapidamente a informacao de seu preco e sabe tambem quantos dias a fita ficou alugada. Assim pode fazer o calculo.

Aqui, eu ficaria na duvida entre Aluguel e um service para o calculo da multa. A primeira ideia é de manter o calculo em Aluguel, mas a informacao da multa teria que vir da Fita, pois de acordo com o tipo da fita é que voce calcula a multa, voce teria em alguel algo como :

    if (fita.atrasoMaiorQueOPermitido(this.diasAlugados())
        return = fita.precoComMultaPorDia() * this.diasAlugados(); 
    
    return fita.preco() * this.diasAlugados();

E por ai voce vai. Depois refatora um pouco mais pra tirar esse if e fazer um polimorfismo melhor para os determinados tipos de fita. Mas o caminho é mais ou menos por ai, acredito eu.

[/quote]