Ponteiros para funções: exemplos

Em uma cidade quente como Cuiabá, ter aparelhos de ar-condicionado é uma necessidade.

Agora, imagine que você trabalha uma empresa que dispõe de diversos aparelhos instalados em todo o prédio, como acontece na UFMT.

Para otimizar o uso dos aparelhos, a empresa deseja desenvolver um dispositivo capaz de ligar, desligar e alterar a temperatura desses equipamentos.

Embora os fabricantes disponibilizem uma biblioteca para a manipulação de seus aparelhos de ar-condicionado, a empresa em que você trabalha possui aparelhos de diversos fabricantes em uma mesma sala. Por isso, o dispositivo que você está desenvolvendo precisa ter a capacidade de se comunicar com todos eles.

🤔 Imaginando o cenário técnico

Vamos considerar, por enquanto, dois fabricantes ar-condicionado: PantanAr e ArARA. Por uma normatização técnica, as empresas devem fornecer bibliotecas que possibilitam controlar o funcionamento de seus produtos, com a mudança de temperatura.

A PantanAr disponibiliza uma biblioteca com as seguintes implementações:

void ligar(int aparelho){
    printf("PantanAr %d tá on! :D \n", aparelho);
}

void desligar(int aparelho){
    printf("PantanAr %d tá off! :( \n", aparelho);
}

void alterarTemperatura(int aparelho, int temp){
    printf("Temperatura do PantanAr %d alterada para %d :)\n", aparelho, temp);
}

Já a ArARA oferece uma biblioteca com as seguintes implementações:

void turnOn(int dsp){
    printf("\nArARA - Device %d on", dsp);
}

void turnOff(int dsp){
    printf("\nArARA - Device %d off", dsp);
}

void alterarTemperatura(int dsp, int t){
    printf("\nArARA - Device %d - Current temperature %d", dsp, t);
}

👨🏻‍💻 Discutindo a implementação da solução

Já vimos que cada empresa oferece uma biblioteca própria para manipular seus aparelhos de ar-condicionado. Na implementação da solução para a nossa empresa, temos que pensar numa estratégia que possibilite lidar com as funções das duas bibliotecas, assim como possibilite uma fácil adequação a um terceiro fabricante, caso um aparelho de uma nova marca seja adquirido.

A melhor estratégia aqui não é chamar diretamente os procedimentos das bibliotecas de cada fabricante, mas sim criar uma biblioteca própria.

A nossa biblioteca

Assumindo que há uma padronização no protótipo dos procedimentos/funções entre os diversos fabricantes, graças a uma norma técnica, a nossa biblioteca pode ser implementada da seguinte forma:

void ligarAparelho(void (*funcaoLigar)(int), int codAparelho){
    funcaoLigar(codAparelho);
}

void desligarAparelho(void (*funcaoDesligar)(int), int codAparelho){
    funcaoDesligar(codAparelho);
}

void mudarTemperatura(void (*funcaoMudarTemperatura)(int), int codAparelho, int temperatura){
    funcaoMudarTemperatura(codAparelho, temperatura);
}

A partir de agora, nosso programa pode lidar exclusivamente com os nomes que atribuímos aos nossos procedimentos. Embora ainda tenhamos que passar o ponteiro para a função da biblioteca de cada fabricante, todo o resto do nosso programa é independente.

Nas próximas aulas, estudaremos conceitos que nos possibilitarão extrair o máximo de benefícios dessa estratégia que começamos a ver aqui.