Existem muitas abordagens válidas para resolver seu problema. Basile Starynkevitch propôs uma abordagem de “burocracia zero” que deixa você com uma interface simples e depende do programador usar adequadamente a interface. Enquanto eu gosto dessa abordagem, apresentarei outra que tem mais engenharia, mas permite ao compilador detectar alguns erros.
Identificar os vários estados o dispositivo pode ser, como Uninitialised
,
Started
, Configured
e assim por diante. A lista deve ser finita.¹
Para cada estado, defina struct
mantendo as informações adicionais necessárias relevantes para esse estado, por exemplo DeviceUninitialised
,
DeviceStarted
e assim por diante.
Empacote todos os tratamentos em um objeto em DeviceStrategy
que os métodos usem estruturas definidas em 2. como entradas e saídas. Assim, você pode ter um DeviceStarted DeviceStrategy::start (DeviceUninitalised dev)
método (ou qualquer que seja o equivalente de acordo com as convenções do seu projeto).
Com essa abordagem, um programa válido deve chamar alguns métodos na sequência imposta pelos protótipos do método.
Os vários estados são objetos não relacionados, isso ocorre por causa do princípio da substituição. Se for útil que essas estruturas compartilhem um ancestral comum, lembre-se de que o padrão de visitante pode ser usado para recuperar o tipo concreto da instância de uma classe abstrata.
Enquanto eu descrevi em 3. uma DeviceStrategy
classe única , há situações em que você pode querer dividir a funcionalidade que ela fornece em várias classes.
Para resumir, os pontos principais do design que descrevi são:
Por causa do princípio da substituição, os objetos que representam estados do dispositivo devem ser distintos e não ter relações de herança especiais.
Empacote tratamentos de dispositivos em objetos iniciais, e não nos objetos que representam os próprios dispositivos, para que cada dispositivo ou estado do dispositivo veja apenas a si mesmo, e a estratégia os veja e expresse possíveis transições entre eles.
Juro que vi uma vez uma descrição de uma implementação de cliente de telnet seguindo estas linhas, mas não consegui encontrá-la novamente. Teria sido uma referência muito útil!
Nota: Para isso, siga sua intuição ou encontre as classes de equivalência de métodos em sua implementação real para a relação “method₁ ~ method₂ iff. é válido usá-los no mesmo objeto ”- supondo que você tenha um grande objeto encapsulando todos os tratamentos no seu dispositivo. Ambos os métodos de listagem de estados fornecem resultados fantásticos.
discovery
ouhandshake
?