제이온

[Objetos] Capítulo 2. Programação Orientada a Objetos

  • Idioma de escrita: Coreana
  • País de referência: Todos os paísescountry-flag
  • TI

Criado: 2024-04-28

Criado: 2024-04-28 13:46

Sistema de Reserva de Filmes


Analisando os Requisitos

  • Pretende-se implementar um sistema de reserva de filmes online.
  • O filme representa as informações básicas sobre o filme.
    • Como título, duração e informações de preço.
  • A exibição representa o evento real em que o público assiste ao filme.
    • Como data de exibição, hora e número de ordem.
  • As pessoas reservam filmes, mas na verdade, seria mais correto dizer que elas reservam uma determinada exibiçãode um filme.
  • Condições de desconto
    • Se o preço será ou não descontado.
    • Condição de ordem: usar o número de ordem da exibição para determinar se haverá desconto.
    • Condição de período: usar a hora de início da exibição do filme para determinar se haverá desconto.
  • Política de desconto
    • Determinar o valor do desconto.
    • Política de desconto em valor: descontar um valor fixo da taxa de reserva.
    • Política de desconto percentual: descontar uma porcentagem do preço original.
  • Cada filme pode ter uma política de desconto atribuída a ele ou não ter nenhuma, e as condições de desconto podem ser combinadas.
  • Se a política de desconto estiver aplicada, mas as condições de desconto não forem atendidas, ou se a política de desconto não estiver aplicada, a taxa não será descontada.


Em direção à Programação Orientada a Objetos

Cooperação, Objetos e Classes

  • Orientação a objetos é orientar-se por objetos.
    • Não devemos pensar em quais atributos e métodos uma classe precisa ter depois de decidir sobre a classe.
    • Devemos decidir quais objetos têm quais estados e comportamentos.
    • Os objetos devem ser vistos não como entidades independentes, mas como membros de uma comunidade que coopera.


Estrutura do programa que segue a estrutura do domínio

  • Domínio refere-se à área em que o usuário usa o programa para resolver um problema.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fe7d22a03-4a24-40e9-8068-bd03b9fd816b%2FUntitled.png?table=block&id=3f1931fc-8ef9-470a-8189-3727146638f6&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/438;" width="2000" height="438"></span>

  • Em geral, o nome da classe deve ser o mesmo ou pelo menos semelhante ao nome do conceito de domínio correspondente.
  • O relacionamento entre as classes também deve ser o mais semelhante possível ao relacionamento entre os conceitos de domínio, tornando a estrutura do programa mais fácil de entender e prever.


Implementando Classes

  • Uma classe é dividida em interno e externo, e para projetar uma boa classe, você precisa decidir quais partes tornar públicas e quais partes ocultar.
    • Os atributos de um objeto são ocultados como privados, e os métodos necessários para modificar o estado interno são abertos como públicos.
  • Ao distinguir entre o interior e o exterior de uma classe, garante-se a autonomia do objeto, fornecendo ao programador a liberdade de implementação.


Objeto Autônomo

  • Um objeto deve ser um objeto autônomo com estado e comportamento.
  • O ato de agrupar dados e funções dentro de um objeto é chamado de encapsulamento.
  • O controle de acesso deve ser usado para reduzir a interferência externa, permitindo que o objeto decida seu próprio comportamento.
  • O princípio de separação entre interface e implementação é um princípio importante a ser seguido na programação orientada a objetos.
    • Interface pública: parte acessível de fora.
    • Implementação: parte acessível apenas de dentro.


Liberdade do Programador

  • O papel do programador é dividido em programador de classe e programador cliente.
    • O programador da classe adiciona novos tipos de dados.
    • O programador cliente usa os tipos de dados adicionados pelo programador da classe.
  • Ocultar implementação
    • O programador da classe pode ocultar a implementação interna fornecendo apenas as partes necessárias ao programador cliente.
    • Como o programador cliente só precisa saber a interface, a quantidade de conhecimento que ele precisa ter é reduzida.


Comunidade de objetos cooperantes

  • Ao representar dinheiro, é melhor encapsulá-lo em um objeto, como Money, em vez de simplesmente declarar uma variável do tipo Long. Ao usar objetos, a comunicação é melhor e operações redundantes podem ser realizadas em um único local.
  • A interação entre objetos para implementar alguma função do sistema é chamada de cooperação.


Uma breve história sobre cooperação

  • A única maneira de um objeto interagir com outro objeto é enviando ou recebendo mensagens.
  • O método é a maneira como ele próprio processa a mensagem recebida.
  • É importante distinguir entre mensagem e método, e é daí que surge o conceito de polimorfismo.


Calculando a Taxa de Desconto

Iniciando a cooperação para calcular a taxa de desconto

  • A classe Movie não contém a lógica detalhada da política de desconto e a delegou para a interface DiscountPolicy. O uso de herança, polimorfismo e abstração é realmente importante.


Política de desconto e condição de desconto

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F7b9b27a5-0dac-4ba7-9552-05b7f8fbdecd%2FUntitled.png?table=block&id=3264f189-6e12-4a55-94d2-75b851320c7a&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/535;" width="2000" height="535"></span>


Herança e Polimorfismo

Dependência em tempo de compilação e dependência em tempo de execução

  • A dependência do código e a dependência do momento de execução podem ser diferentes.
  • Quanto mais diferentes forem as dependências, mais difícil será entender o código, mas o código se tornará mais flexível e extensível.


Programação por diferença

  • A herança permite que novas classes sejam adicionadas facilmente e rapidamente com base em classes existentes, e a implementação da classe pai pode ser reutilizada.
  • O método de criar uma nova classe adicionando apenas as partes diferentes da classe pai é chamado de programação por diferença.


Herança e Interface

  • A herança faz com que a classe filha herde todas as interfaces fornecidas pela classe pai.
  • A interface define uma lista de mensagens que um objeto pode entender.
  • Movie está enviando uma mensagem calculateDiscountAmount para DiscountPolicy. Do ponto de vista de Movie, não importa qual instância de classe responde, desde que responda com sucesso.
  • Portanto, tanto AmountDiscountPolicy quanto PercentDiscountPolicy podem cooperar com Movie em vez de DiscountPolicy.
  • Essa capacidade da classe filha substituir a classe pai é chamada de upcasting. Isso ocorre porque parece que a classe filha é automaticamente convertida para o tipo da classe pai.


Polimorfismo

  • Polimorfismo é a capacidade de responder de forma diferente dependendo do tipo de objeto quando a mesma mensagem é recebida.
    • Movie envia a mesma mensagem, mas qual método é realmente executado depende de qual classe o objeto que recebe a mensagem é.
  • O polimorfismo é baseado no fato de que a dependência em tempo de compilação e a dependência em tempo de execução de um programa podem ser diferentes.
  • Como o polimorfismo determina qual método será executado em tempo de execução, ele é chamado de vinculação tardia ou vinculação dinâmica.


Interface e Polimorfismo

  • Se você não precisa compartilhar a implementação e deseja compartilhar apenas a interface, pode usar uma interface em vez de uma classe abstrata.


Abstração e Flexibilidade

O poder da abstração

  • Vantagens da abstração
    • Se você olhar apenas para a hierarquia de abstração, poderá descrever a política de requisitos em um nível alto.
    • O design fica mais flexível.


Design flexível

  • A abstração evita que o design seja vinculado a situações específicas, permitindo que um design flexível seja criado.


Trade-off entre classe abstrata e interface


  • Atualmente, NoneDiscountPolicy não é realmente necessário, pois se não houver condição de desconto no método calculateDiscountAmount() de DiscountPolicy, 0 será retornado, então não há problema. No entanto, o usuário precisa inserir uma política None sem condição de desconto como argumento para Movie, então ela foi adicionada.
  • Portanto, a classe NoneDiscountPolicy é confusa do ponto de vista do usuário, então se ela for modificada como abaixo, será mais fácil de entender.



  • Como mostrado acima, a ideia é abstrair DiscountPolicy como uma interface e dividi-la em NoneDiscountPolicy, que é sua implementação, e DefaultDiscountPolicy, que representa uma política de desconto geral.

<span class="image-inline ck-widget" contenteditable="false"><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F712983a9-3937-4265-82fe-66a144c44a0f%2FUntitled.png?table=block&id=f5ca651c-d03c-4a6c-97e9-7443ee5649a0&spaceId=b453bd85-cb15-44b5-bf2e-580aeda8074e&width=2000&userId=80352c12-65a4-4562-9a36-2179ed0dfffb&cache=v2" alt="Untitled" style="aspect-ratio:2000/886;" width="2000" height="886"></span>

  • Você pode pensar que adicionar uma interface apenas para NoneDiscountPolicy é ineficaz em relação ao aumento da complexidade.
  • Você deve estar ciente de que tudo relacionado à implementação pode ser alvo de trade-off e projetar com base nisso. Ou seja, todo código que você escreve deve ter uma razão lógica.


Reutilização de código

  • A herança pode ser usada para reutilizar código.
  • No entanto, para a reutilização de código, é melhor usar composição em vez de herança.
  • No código atual, a maneira como Movie reutiliza o código de DiscountPolicy é através da composição.
  • Se Movie fosse a classe pai e fosse dividida em AmountDiscountMovie e PercentDiscountMovie, seria considerado o uso de herança.


Herança

  • Desvantagens da herança
    • Viola o encapsulamento.
      • Você precisa saber a estrutura interna da classe pai.
      • É mais provável que a classe filha também precise ser modificada quando a classe pai for modificada.
    • Torna o design menos flexível.
      • O relacionamento entre a classe pai e a classe filha é determinado em tempo de compilação.
      • É impossível alterar o tipo de objeto em tempo de execução.
      • No entanto, com a composição, o lado que usa pode substituir a instância em tempo de execução através de métodos como changeDiscountPolicy().


Composição

  • O método de reutilizar código apenas por meio de mensagens definidas na interface é chamado de composição.
  • Pode implementar o encapsulamento e manter um acoplamento fraco.
  • Quando uma interface é reutilizada para polimorfismo, herança e composição devem ser combinadas.
    • Por exemplo, a interface DiscountPolicy precisa usar herança para implementar suas classes filhas.


Fontes

  • Objetos

Comentários0