
Passo 1 de 6
Separar as responsabilidades de um atendimento
Identifique quais estados, regras e operações pertencem à fila e quais pertencem ao guichê em uma simulação de atendimento.
Trilha de aprendizado · Nível 7 · Tutorial 4
Distribuir responsabilidades entre objetos colaboradores e implementar uma classe que delega parte de suas operações a outros objetos.
Separar as responsabilidades de um atendimento
Identifique quais estados, regras e operações pertencem à fila e quais pertencem ao guichê em uma simulação de atendimento. 2 min
Conectar objetos pela inicialização
Ligue um Guiche a uma FilaAtendimento recebendo e armazenando a instância colaboradora durante a inicialização. 3 min
Delegar sem assumir as regras do colaborador
Implemente o fluxo de atendimento fazendo o guichê solicitar a próxima pessoa pela interface pública da fila, sem duplicar suas regras ou acessar seus dados internos. 4 min
Decidir entre um colaborador exclusivo e compartilhado
Compare configurações em que dois guichês usam a mesma fila ou filas independentes e preveja os efeitos sobre o estado de cada objeto. 3 min
Reconhecer quando uma função é suficiente
Compare uma classe colaboradora com uma função e escolha conforme a necessidade de manter estado e regras entre operações. 2 min
Aplicar e revisar a composição
Integre fila, guichê e função de formatação em uma simulação executável e revise as decisões de composição. 5 min

Passo 1 de 6
Identifique quais estados, regras e operações pertencem à fila e quais pertencem ao guichê em uma simulação de atendimento.
Imagine uma simulação em memória: pessoas fictícias entram em uma fila e são chamadas por guichês. Uma única classe até poderia guardar a lista de pessoas, decidir quem sai primeiro, identificar o guichê e contar seus atendimentos. Porém, ela estaria controlando dois estados com regras diferentes.
Exemplo
Se a mesma classe responde a perguntas como “quem é a próxima pessoa?” e “quantos atendimentos este guichê realizou?”, há um sinal de responsabilidades concentradas. A primeira pergunta trata da fila; a segunda, do guichê.
A FilaAtendimento cuida das pessoas aguardando, preserva a ordem de entrada e retira a próxima pessoa. O Guiche mantém sua identificação, registra seu total de atendimentos e coordena cada atendimento. A separação não depende do número de linhas: mesmo uma classe curta pode misturar responsabilidades distintas.
Observe que cada objeto concentra os dados e as operações relacionados à própria responsabilidade.

A fila controla quem aguarda e a ordem; o guichê controla sua identidade e seu total de atendimentos.
Associe cada responsabilidade à classe adequada.
Toque em um item e depois no par correspondente.

Passo 2 de 6
Ligue um Guiche a uma FilaAtendimento recebendo e armazenando a instância colaboradora durante a inicialização.
Na composição, um objeto organiza seu trabalho com a ajuda de outros objetos. Aqui, o Guiche usa uma FilaAtendimento: a fila conserva as pessoas aguardando, enquanto o guichê mantém sua identificação e seu total de atendimentos.
Essa ligação não transforma o guichê em um tipo de fila. São objetos com responsabilidades distintas, conectados por uma referência.
O atributo fila do objeto Guiche aponta para o objeto FilaAtendimento. A fila não é copiada para dentro do guichê.

O guichê mantém uma referência para a fila colaboradora; cada objeto continua responsável pelo próprio estado.
Primeiro, crie a instância de FilaAtendimento. Depois, passe esse objeto ao inicializar o Guiche. O parâmetro fila recebe a referência, e self.fila = fila a conserva em um atributo de instância.
Neste exemplo, o guichê recebe a fila pronta em vez de criar ou copiar seus dados.
class FilaAtendimento:
def __init__(self):
self._pessoas = []
class Guiche:
def __init__(self, identificacao, fila):
self.identificacao = identificacao
self.total_atendimentos = 0
self.fila = fila
fila_principal = FilaAtendimento()
guiche_1 = Guiche("G1", fila_principal)Dica
O argumento é fila_principal, uma instância já criada. Passar FilaAtendimento sem parênteses entregaria a própria classe. Passar fila_principal._pessoas entregaria apenas a coleção interna, eliminando a colaboração com o objeto responsável pelas regras da fila.
Complete a última linha para guardar no guichê exatamente a instância recebida:
class Guiche:
def init(self, identificacao, fila):
self.identificacao = identificacao
self.total_atendimentos = 0
self.fila = _
Considerando que Guiche.__init__ recebe os parâmetros identificacao e fila, qual opção estabelece corretamente a colaboração explícita?

Passo 3 de 6
Implemente o fluxo de atendimento fazendo o guichê solicitar a próxima pessoa pela interface pública da fila, sem duplicar suas regras ou acessar seus dados internos.
O Guiche coordena o atendimento, mas não decide como retirar alguém da fila. Em atender_proximo, ele chama o método público da FilaAtendimento armazenada em self.fila.
A fila continua responsável por preservar a ordem de entrada e rejeitar uma retirada quando não há ninguém aguardando. O guichê registra somente um atendimento que realmente começou.

A retirada acontece na fila; o total só é atualizado no guichê depois que uma pessoa é devolvida com sucesso.
Observe a ordem das instruções em atender_proximo: primeiro ocorre a retirada; somente depois o total é incrementado.
class FilaAtendimento:
def __init__(self):
self._pessoas = []
def entrar(self, pessoa):
self._pessoas.append(pessoa)
def retirar_proxima(self):
if not self._pessoas:
raise ValueError("Não há pessoas aguardando")
return self._pessoas.pop(0)
class Guiche:
def __init__(self, identificacao, fila):
self.identificacao = identificacao
self.fila = fila
self.total_atendimentos = 0
def atender_proximo(self):
pessoa = self.fila.retirar_proxima()
self.total_atendimentos += 1
return pessoa
fila = FilaAtendimento()
fila.entrar("Ana")
fila.entrar("Bruno")
guiche = Guiche("G1", fila)
print(guiche.atender_proximo())
print(guiche.total_atendimentos)Dica
Se retirar_proxima() rejeitar a operação, a execução não chega a self.total_atendimentos += 1. Assim, uma tentativa com a fila vazia não é registrada como atendimento realizado.
Atenção
O Guiche não deve usar self.fila._pessoas, aplicar pop(0) nem repetir a verificação de fila vazia. Isso duplicaria no guichê os dados, a ordem de retirada e as validações que pertencem à FilaAtendimento.
Coloque as ações de atender_proximo na ordem correta.
Analise esta versão de atender_proximo.
def atender_proximo(self):
self.total_atendimentos += 1
return self.fila._pessoas.pop(0)Por que essa implementação invade a responsabilidade da fila? Explique também o que acontece com total_atendimentos quando a fila está vazia.
Escreva pelo menos 60 caracteres (0/60).

Passo 4 de 6
Compare configurações em que dois guichês usam a mesma fila ou filas independentes e preveja os efeitos sobre o estado de cada objeto.
Dois guichês podem receber a mesma instância de FilaAtendimento ou instâncias diferentes.
Essa escolha deve representar o funcionamento do domínio. Compartilhar um colaborador não é um erro por definição.

À esquerda, duas referências chegam ao mesmo objeto de fila. À direita, cada referência chega a um objeto de fila diferente.
No código a seguir, guiche_1 e guiche_2 guardam uma referência para o mesmo objeto fila_comum. As chamadas são sequenciais: primeiro o guichê 1 retira uma pessoa; depois, o guichê 2 encontra a fila já modificada.
O atributo total_atendimentos, porém, pertence a cada instância de Guiche. Por isso, os totais continuam separados.
Considere as classes implementadas nos steps anteriores: a fila controla a ordem e o guichê delega a retirada.
fila_comum = FilaAtendimento(["Ana", "Beto", "Caio"])
guiche_1 = Guiche("G1", fila_comum)
guiche_2 = Guiche("G2", fila_comum)
print(guiche_1.atender_proximo()) # Ana
print(guiche_2.atender_proximo()) # Beto
print(fila_comum.pessoas_aguardando()) # ('Caio',)
print(guiche_1.total_atendimentos) # 1
print(guiche_2.total_atendimentos) # 1Dica
O compartilhamento ocorre porque a mesma instância, fila_comum, foi passada aos dois inicializadores. Criar duas variáveis apontando para esse objeto não criaria duas filas.
Quando cada guichê deve atender seu próprio grupo de pessoas, crie duas instâncias de FilaAtendimento e passe uma para cada guichê. Agora, cada retirada afeta somente a fila correspondente.
As duas filas podem conter dados diferentes e avançar em ritmos diferentes.
fila_1 = FilaAtendimento(["Ana", "Beto"])
fila_2 = FilaAtendimento(["Caio", "Dora"])
guiche_1 = Guiche("G1", fila_1)
guiche_2 = Guiche("G2", fila_2)
print(guiche_1.atender_proximo()) # Ana
print(guiche_2.atender_proximo()) # Caio
print(guiche_1.atender_proximo()) # Beto
print(fila_1.pessoas_aguardando()) # ()
print(fila_2.pessoas_aguardando()) # ('Dora',)
print(guiche_1.total_atendimentos) # 2
print(guiche_2.total_atendimentos) # 1Uma fila contém Lia, Noé e Ivo, nessa ordem. G1 e G2 recebem essa mesma instância. Primeiro, G2.atender_proximo() é chamado; depois, G1.atender_proximo().
Qual é o estado após as duas chamadas?
Uma empresa possui duas unidades físicas, Norte e Sul. Cada unidade distribui suas próprias senhas, e uma pessoa atendida no Norte não deve sair da fila do Sul. Você usaria uma fila compartilhada ou filas exclusivas? Justifique com base no estado que será alterado.
Escreva pelo menos 50 caracteres (0/50).

Passo 5 de 6
Compare uma classe colaboradora com uma função e escolha conforme a necessidade de manter estado e regras entre operações.
Uma classe colaboradora é útil quando precisa manter estado entre operações e proteger regras relacionadas a ele. FilaAtendimento, por exemplo, conserva as pessoas que ainda aguardam e controla a ordem de retirada.
Já uma operação que recebe todos os dados necessários, produz um resultado e não precisa guardar nada para a próxima chamada costuma ser uma boa candidata a função. O critério principal não é o tamanho do código, mas a existência de estado próprio persistente.
À esquerda, várias operações consultam e alteram o mesmo estado da fila. À direita, cada formatação depende apenas dos dados recebidos naquela chamada.

A fila precisa conservar estado; a formatação pode apenas transformar entradas em um texto.
A mensagem de atendimento pode receber o identificador do guichê, o nome da pessoa e o total já atendido. Como todos os dados chegam por parâmetros, a operação não precisa de estado próprio nem de uma nova classe.
Cada chamada é independente: a função usa somente os argumentos recebidos e retorna uma nova string.
def formatar_atendimento(guiche, pessoa, total_atendimentos):
return (
f"Guichê {guiche} atendeu {pessoa}. "
f"Total do guichê: {total_atendimentos}."
)
mensagem = formatar_atendimento(
guiche="A",
pessoa="Lia",
total_atendimentos=3,
)
print(mensagem)
# Guichê A atendeu Lia. Total do guichê: 3.Dica
A ausência de estado próprio favorece o uso de uma função, mas não estabelece que toda classe sem estado esteja errada. A decisão depende do papel da operação no programa. Neste cenário, criar uma classe apenas para abrigar a formatação não acrescentaria uma responsabilidade persistente.
Associe cada operação à alternativa de modelagem mais adequada neste cenário.
Toque em um item e depois no par correspondente.
Uma operação recebe o identificador do guichê, o nome da pessoa e o total de atendimentos, então retorna uma mensagem. Ela não mantém histórico nem configuração entre chamadas. Você escolheria uma função ou uma classe colaboradora? Justifique e indique que tipo de mudança poderia tornar uma classe mais útil.
Escreva pelo menos 60 caracteres (0/60).

Passo 6 de 6
Integre fila, guichê e função de formatação em uma simulação executável e revise as decisões de composição.
A simulação será formada apenas pelos elementos já estudados:
FilaAtendimento mantém as pessoas, preserva a ordem e rejeita retiradas quando está vazia.Guiche mantém sua identificação e seu total de atendimentos. Para atender, delega a retirada à fila recebida em __init__.formatar_atendimento recebe os dados necessários e devolve uma mensagem. Como não precisa manter estado entre chamadas, continua sendo uma função.A mesma implementação permite conectar dois guichês a uma fila comum ou entregar uma fila exclusiva a cada um.
Compare as referências entre os objetos. Na configuração compartilhada, os dois guichês apontam para a mesma fila. Na exclusiva, cada guichê aponta para uma fila diferente.

Compartilhar ou não a fila é uma decisão explícita feita ao criar os guichês.
Crie um arquivo chamado atendimento.py, copie todo o código abaixo e execute-o com python atendimento.py. Observe primeiro a fila compartilhada e depois as filas exclusivas. Se quiser repetir o experimento, troque apenas os nomes fictícios, sem alterar a ligação entre os objetos.
O código usa somente a interface pública da fila para adicionar e retirar pessoas.
class FilaAtendimento:
def __init__(self):
self._pessoas = []
def entrar(self, pessoa):
self._pessoas.append(pessoa)
def retirar_proxima(self):
if not self._pessoas:
raise ValueError("Não há pessoas aguardando")
return self._pessoas.pop(0)
class Guiche:
def __init__(self, identificacao, fila):
self.identificacao = identificacao
self.total_atendimentos = 0
self._fila = fila
def atender_proximo(self):
pessoa = self._fila.retirar_proxima()
self.total_atendimentos += 1
return pessoa
def formatar_atendimento(identificacao, pessoa):
return f"Guichê {identificacao} atendeu {pessoa}"
print("=== FILA COMPARTILHADA ===")
fila_comum = FilaAtendimento()
fila_comum.entrar("Ana")
fila_comum.entrar("Bruno")
guiche_1 = Guiche("1", fila_comum)
guiche_2 = Guiche("2", fila_comum)
pessoa = guiche_1.atender_proximo()
print(formatar_atendimento(guiche_1.identificacao, pessoa))
pessoa = guiche_2.atender_proximo()
print(formatar_atendimento(guiche_2.identificacao, pessoa))
print("Total do guichê 1:", guiche_1.total_atendimentos)
print("Total do guichê 2:", guiche_2.total_atendimentos)
print("Tentativa com a fila vazia:")
total_antes = guiche_1.total_atendimentos
try:
guiche_1.atender_proximo()
except ValueError as erro:
print("Retirada rejeitada:", erro)
print("Total antes:", total_antes)
print("Total depois:", guiche_1.total_atendimentos)
print("\n=== FILAS EXCLUSIVAS ===")
fila_exclusiva_1 = FilaAtendimento()
fila_exclusiva_2 = FilaAtendimento()
fila_exclusiva_1.entrar("Rita")
fila_exclusiva_2.entrar("Rita")
guiche_3 = Guiche("3", fila_exclusiva_1)
guiche_4 = Guiche("4", fila_exclusiva_2)
pessoa = guiche_3.atender_proximo()
print(formatar_atendimento(guiche_3.identificacao, pessoa))
pessoa = guiche_4.atender_proximo()
print(formatar_atendimento(guiche_4.identificacao, pessoa))
print("Total do guichê 3:", guiche_3.total_atendimentos)
print("Total do guichê 4:", guiche_4.total_atendimentos)Exemplo
Na fila compartilhada, Ana é retirada pelo guichê 1 e Bruno pelo guichê 2. A terceira retirada é rejeitada, e o total do guichê 1 permanece igual a 1.
Nas filas exclusivas, cada fila contém sua própria ocorrência de Rita. Por isso, os guichês 3 e 4 conseguem atender uma pessoa, mesmo depois de um deles realizar a retirada.
Dica
A retirada ocorre antes do incremento. Se retirar_proxima() sinalizar que a fila está vazia, a execução não chega à atualização de total_atendimentos. Assim, a fila protege sua regra e o guichê não registra um atendimento que não aconteceu.
Após executar o programa, responda:
atender_proximo.Escreva pelo menos 180 caracteres (0/180).
Resumo
Use estes critérios ao distribuir responsabilidades em novos programas.
__init__ e armazene sua referência em um atributo de instância.Parabéns! Você concluiu: Compor objetos com responsabilidades distintas
60 XP
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks