Duvidas java, logica e orientação a objetos [AJUDA]

bom dia pessoal, estou trabalhando em um projeto de cadastro de funcionários fiz a seguinte classe abstrata Funcionário.

package entidades;

public abstract class Funcionario {

private String nome;
private Integer id;
private Cargo cargo;
private String tel;
private String email;

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public Integer getId() {
	return id;
}

public void setId(Integer id) {
	this.id = id;
}

public String getEmail() {
	return email;
}

public void setEmail(String email) {
	this.email = email;
}

public String getTel() {
	return tel;
}

public void setTel(String tel) {
	this.tel = tel;
}

public Cargo getCargo() {
	return cargo;
}

public void setCargo(Cargo cargo) {
	this.cargo = cargo;
}

}

também fiz as classes Diretor e Gerente que estendem a classe Funcionário

public class Diretor extends Funcionario implements Administracao {

private static Diretor instance;

public static Diretor getInstance() {
}

public void montarProjeto(Projeto p, Gerente g, Diretor d, char status) {
}

// public Gerente associarGerente(Gerente g) {
//
// //montarProjeto()
// }

static void verRelatorios() {
}

static void criarRelGerais() {
}

}

public class Gerente extends Funcionario implements Administracao, Gerencia {
static List listdes = new ArrayList<>();

public void montarEquipe(Projeto p, List<Integer> des) {		
}

public static void escalaDesenvolvedores(Integer des) {	
}

public static List<Integer> buscaDes() {
	return listdes;
}

public void planejaAtividades() {
}

public void CriaRelatorios() {
}

}

observem que a classe Funcionario possui o atributo Cargo da classe Cargo

public class Cargo {
private Integer idCargo;
private String nomeCargo;

public Cargo() {
}

public Cargo(String nomeCargo) {
	super();
	this.nomeCargo = nomeCargo;
}

public String getNomeCargo() {
	return nomeCargo;
}

public void setNomeCargo(String nomeCargo) {
	this.nomeCargo = nomeCargo;
}

public Integer getIdCargo() {
	return idCargo;
}

public void setIdCargo(Integer idCargo) {
	this.idCargo = idCargo;
}

@Override
public String toString() {
	return "Cargo [idCargo = " + idCargo + ", nomeCargo = " + nomeCargo + "]";
}

}

minha duvida é, qual a melhor forma de cadastrar novos funcionários? Diretor (a empresa possui apenas UM diretor) e gerentes(podem existir mais de um gerente ) possuem métodos
específicos, como faço para que os objetos possam utilizar seus métodos específicos? o projeto esta em anexo.

programacao.rar (12,0 KB)

Por exemplo, dentro de funcionário você tem o metodo calculaBonificacao que também é abstrato, e dentro de cada subclasse de funcionario você sobrescreve o método para que quando determinado objeto chamar o método, ele utilize o de sua classe que fora sobreescrito. Quanto ao diretor tem que fazer ele ser singleton, ou seja, só pode ser instanciado uma unica vez. Acredito que seja isso, se estiver errado me corrigam por favor.

Abraço.