@startuml package ndef { class Record { } class RecordType { } class RecordPayload { } class RecordID { } Record *-- RecordType Record *-- "0..1" RecordPayload Record *-- "0..1" RecordID abstract RecordParser { +RecordParser() +{abstract} bool parse(const Record&) #~RecordParser() } abstract GenericRecordParser<ParserImplementation, ParsingResult> { +GenericRecordParser() +bool parse(const Record&) +void set_delegate(Delegate* delegate) #~GenericRecordParser() } interface GenericRecordParserConcept<ParsingResult> { +bool do_parse(const Record& record, ParsingResult& parsing_result) } interface GenericRecordParser::Delegate<ParsingResult> { +{abstract} void on_record_parsed(const ParsingResult& record, const RecordID* id) #~Delegate() } RecordParser <|-- GenericRecordParser GenericRecordParser <|-- GenericRecordParserConcept GenericRecordParser +-- "0..1" GenericRecordParser::Delegate note as N1 GenericRecordParserConcept model the concept that must be implemented by GenericRecordParser childs. It doesn't exist in the hierarchy. end note N1 - GenericRecordParser N1 - GenericRecordParserConcept note bottom of "GenericRecordParser::Delegate" Implemented by the client of the parsing operation. end note class RecordParserChain { +RecordParserChain() +~RecordParserChain() +bool parse(const Record& record) +void set_next_parser(RecordParser* parser) } note bottom of "RecordParserChain" Chain of responsibility pattern. end note Record - RecordParserChain: Parse > RecordParserChain o- "*" RecordParser } @enduml