Como obrigar classes filhas a implementarem um construtor?

Bom dia, estou em um cenário que tenho três classes diferentes, as três são destinadas a regras de negócio e nenhuma herda alguma classe.
A partir de agora quero que todas as classes que são regras de negócio tenham um construtor em comum, com a mesma lógica.
Como posso fazer para que toda classe destinada a regra de negócio seja obrigada a ter esse construtor?

public class BusinessCentral {

    BusinessCentral(int idUsuario, int idEndPoint){

        /*...lógica... */

    }

}

Criei a classe acima e estive pensando em fazer as outras classes que representam a regra de negócio herdassem dela, como posso obrigar que as classes de regra de negócio que herdem da BusinessCentral sejam obrigadas a ter como construtor o mesmo construtor de BusinessCentral?

Uma maneira de fazer isso é fazer com que suas classes implementem uma interface ou estendam uma classe abstrata.
As classes que estendem a classe abstrata precisam ser marcadas como finais e tornei os construtores "packae privados.
Essas classes eu adicionei em um “modelo” de pacote separado. Dessa forma o cliente “Principal” não tem acesso aos construtores.
Agora, o próximo passo é criar uma classe Helper “BusinessRules” que tem métodos públicos estáticos, que o cliente “Principal” pode usar para criar as diferentes regras de negócios

public class Main {

public static void main(String[] args) {
	BusinessCentral ruleb = BusinessRules.getRuleB(1234, 635);
	BusinessCentral rulea = BusinessRules.getRuleA(7777, 9999);
	System.out.println(ruleb);
	System.out.println(rulea);
	rulea = BusinessRules.getRuleA(-234, 9899); // invalid value
	System.out.println(rulea);

}

}
package model;

public abstract class BusinessCentral {
protected int idUsuario;
protected int idEndPoint;

protected BusinessCentral(int idUsuario, int idEndPoint) {
	if(idUsuario < 0 || idEndPoint < 0)
		throw new IllegalArgumentException("May not be negative");
	this.idUsuario = idUsuario;
	this.idEndPoint = idEndPoint;
}



@Override
public String toString() {
	return "BusinessCentral [idUsuario=" + idUsuario + ", idEndPoint=" + idEndPoint + 
			"Business Rule = " + this.getClass().getName() + "]";
} 

package model;

public final class BusinessRuleA extends BusinessCentral {

 BusinessRuleA(int idUsuario, int idEndPoint) {
	super( idUsuario,  idEndPoint);
}

}
package model;

public class BusinessRuleB extends BusinessCentral {

BusinessRuleB(int idUsuario, int idEndPoint) {
	super( idUsuario,  idEndPoint);
}

}
package model;

/*

  • Helper class with static public methods to create the different BusinessRules

*/

public class BusinessRules {

public static BusinessCentral getRuleA(int idUsuario, int idEndPoint) {
	return new BusinessRuleA(idUsuario,idEndPoint);
}

public static BusinessCentral getRuleB(int idUsuario, int idEndPoint) {
	return new BusinessRuleB(idUsuario,idEndPoint);
}

}

1 curtida

Uma correção do meu lado.
Ambos BusinessRuleA e BusinessRule devem ser declarados
classe final seus construtores “empacotam privado” para que os clientes os estendam ou instanciem fora do pacote de modo. Dessa forma, o cliente é forçado a usar a classe Helper “BusinessRules” para instanciá-los. Aqui é onde você aplica as regras, etc.
Um exemplo disso é o uso de java.nio. Instâncias da interface Path são criadas usando a classe Helper Paths. Caminho myPath = Pathy.get (String)

1 curtida

É só você remover o construtor padrão da superclasse e definir o construtor parametrizado.

Mas isso não é uma boa ideia, pois você estárá obrigando a utilizar herança nas suas regras de negócio.
Herança gera acomplamento forte.
Acomplamento forte aumenta o risco de bugs e o trabalho de manutenção.

Eu sugiro utilizar interface pra isso.

Se quiser, também pode se basear num framework de regras de negócio que criei há alguns anos, além de usar interfaces, ele permite encadear diferentes regras de forma a criar uma só, ou até criar um repositório de regras de negócio reutilizáveis.

Dê uma olhada: https://github.com/staroski/rules
A documentação está nos javadocs da classe Rule e da interface Specification.

Aqui vai um exemplo de código:

import br.com.staroski.rules.*;

public class Exemplo {

	public static void main(String[] args) {
		// primeiro instanciamos as regras (Rule) a partir de suas especificações (implementações da interface Specification)

		// Nome é uma classe que implementa Specification para validar o nome de uma Pessoa
		Rule<Pessoa> nome = Rule.create(new Nome());

		// Idade é uma classe que implementa Specification para validar a idade de uma Pessoa
		Rule<Pessoa> idade = Rule.create(new Idade());

		// Sexo é uma classe que implementa Specification para validar o sexo de uma Pessoa
		Rule<Pessoa> sexo = Rule.create(new Sexo());

		// agora criamos uma pessoa com nome, idade e sexo validos
		Pessoa pessoa = new Pessoa("Fulano", 30, 'M');

		// també podemos criar uma regra só que corresponde à união das três regras: nome, idade e sexo
		// e assim podemos validar três campos diferente com um único if
		if (nome.and(idade).and(sexo).isSatisfiedBy(pessoa)) {
			System.out.println("O nome, idade e sexo da pessoa atendem as regras\n");
		}

		// em seguida criamos uma pessoa com nome, idade e sexo inválidos
		pessoa = new Pessoa("FuLaNo", -1, 'S');

		// novamente criamos uma regra só que corresponde às três regras: nome, idade e sexo
		// armazenamos essa regra numa variável
		Rule<Pessoa> regra = nome.and(idade).and(sexo);

		// validamos as três regras, com um único if
		if (regra.not().isSatisfiedBy(pessoa)) {
			System.out.println("A pessoa não atendeu as seguintes regras:");

			// se a pessoa não atendeu às regras,
			// usamos a variável declarada para obter os detalhes
			for (String detalhe : regra.getDetails()) {
				System.out.println(detalhe);
			}
		}
	}
}
1 curtida

me ajudem aqui também pfvr

Mas estou tendo dificuldade com isso. Preciso criar uma classe que receba a quantidade de filmes que a pessoa assistiu e some a duração dos filmes. Aqui esta o que fiz por enquanto (Não sei se está certo). A parte de receber a quantidade de filmes assistidos até que deu certo mas não consigo entender o da soma. Então fiz assim:

import java.util.Scanner;
public class Duracao {
   private Scanner entrada;
   public void contaTempo () {

      String duracao = null; // formato x.xx:xx
      int qtdFilmes;
      int totalDuracao = Integer.valueOf(duracao);

      entrada = new Scanner(System.in);
      entrada.useDelimiter("\r\n");

      System.out.print("\n Entre com a quantidade de filmes que voce vai assistir: ");
      qtdFilmes = entrada.nextInt();

      for (int i = 0; i < qtdFilmes; i++){

         System.out.print("\n Entre com a duração do filme: (x.xx:xx");
         duracao = entrada.next();

         totalDuracao = duracao + totalDuracao (Integer.valueOf(duracao));
      }
   }
}
import java.util.Scanner;
public class Duracao {
   private Scanner entrada;
   public void contaTempo () {

      String duracao = null; // formato x.xx:xx
      int qtdFilmes;
      int totalDuracao;

      entrada = new Scanner(System.in);
      entrada.useDelimiter("\r\n");

      System.out.print("\n Entre com a quantidade de filmes que voce vai assistir: ");
      qtdFilmes = entrada.nextInt();

      for (int i = 0; i < qtdFilmes; i++){

         System.out.print("\n Entre com a duração do filme: (x.xx:xx");
         duracao = entrada.next();

         totalDuracao+ = duracao;
      }
   }
}

Tenta substituir por isso e vê se roda. Acho que você tá confundindo o uso desse Integer.valueOf(). Recomendo dar uma olhada nesses dois videos: https://www.youtube.com/watch?v=U0dcVFvJIhk&ab_channel=LoianeGroner e https://www.youtube.com/watch?v=M_YRtU4xRWE&ab_channel=LoianeGroner

1 curtida

Vish , muito obrigada!