Publish to my blog (weekly)

    • you define a publish-subscribe mechanism to notify multiple objects about any events that happen to the object they're subscribed to - it is Observer.
    • Observer, also known as Dependents or Publish-Subscribe, belongs to the category of behavioural design patterns.
    • Publisher (Subject)
    • (Optional) Concrete Publishers
    • Subscriber (Observer)
    • Concrete Subscribers
    • Client
    • The primary goal of the Mediator design pattern is to replace many-to-many relationships between objects with one-to-many relationships by using the dedicated mediator object that handles the communication part.
    • Observer allows establishing a dynamic one-way connection between objects, where some objects act as subordinates of others.
    • reduce dependencies between a set of interacting objects by decoupling the interaction logic from the objects and moving it to a dedicated controller - it is the Mediator.
    • Mediator, also known as Intermediary or Controller, is a behavioural design pattern
    • the main target of the Mediator design pattern is to move from the communicating object dependencies chaos provided on the left to the decoupled one provided on the right:
    • communicating objects are called colleagues
    • the object that controls and coordinates the interaction is called *drums rolls* the mediator.
    • Mediator
    • ConcreteMediator
    • encapsulates relations between components
    • (Optional) Abstract Component or Component Interface
    • Each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague (component).
    • Concrete component or Colleague
    • You want to reuse the component elsewhere
    • You want to make changes in some of the classes, but they affect other dependencies.
    • the relationship logic between objects is extracted to a separate class, hence the changes could be implemented without directly affecting the rest of the components.
    • there is a need to add communicating objects at run-time.
    • the mediator class takes care of the communication logic and all the dependencies between objects,
    • to add or remove those dependencies later from the code
    • make sure that the mediator class is only responsible for the communication part
    •  receives the notification from the notification hub
    • TeamNotificationHub is a concrete notification hub that extends the abstract class NotificationHub and implements its abstract methods
    • a notification hub property
    • register team members
    • NotificationHub? notificationHub;
    • void receive(String from, String message) {
      lastNotification = '$from: "$message"';
      }
    • final _teamMembers = <TeamMember>[];
    • members?.forEach(register);
    • final filteredMembers = _teamMembers.where((m) => m != sender);
    • final filteredMembers =
      _teamMembers.where((m) => m != sender).whereType<T>();
    • late final NotificationHub _notificationHub;
    • _notificationHub = TeamNotificationHub(members: _members);
    • onPressed: _sendToAll,
    • onPressed: _sendToQa,
    • onPressed: _sendToDevelopers,
    • onPressed: _addTeamMember,
    • members: _notificationHub.getTeamMembers(),
    • onTap: _sendFromMember,
    • Specific team members do not contain any reference to the others, they are completely decoupled
    • a behavioural design pattern that enables loose coupling between the sender of a request and its receiver - the Chain of Responsibility.
    • Visitor belongs to the category of behavioural design patterns.
    • When clients traverse the object structure, the accept method is called on each element to delegate the request to the specific visitor object, which is passed to the method as a parameter. Then, the specific method of the visitor object is called (the request is delegated), hence performing the actual request. That's the main idea of a double-dispatch operation - the client sends the request to the component, while the component delegates the request to the specific visitor's method.
    • the Visitor design pattern allows gathering related operations into a single class without spreading the implementation details across the whole object structure.
    • when you want to accumulate a state while traversing an object structure - there is no need to pass the state to operations that perform the accumulation since the state is stored in the visitor object itself and is accessible by all the specific visitor methods.
    • declares a visit operation for each concrete element class in the object structure.
    • Visitor
    • Concrete visitors
    • Element
    • Concrete elements
    • Client
    • initialises the concrete visitor object
    • usually contains a collection or a complex object structure
    • HumanReadableVisitor and XmlVisitor are concrete visitor classes that implement visit methods for each specific file type.
    • VisitorExample contains a list of visitors implementing the IVisitor interface
    • The selected visitor is used to format the visible file structure as text and provide it to the UI.
    • the composite file structure.
    • String accept(IVisitor visitor);

    • String accept(IVisitor visitor) {
      return visitor.visitAudioFile(this);
      }

    • String accept(IVisitor visitor) {
      return visitor.visitImageFile(this);
      }

    • String accept(IVisitor visitor) {
      return visitor.visitTextFile(this);
      }

    • String accept(IVisitor visitor) {
      return visitor.visitVideoFile(this);
      }

    • String accept(IVisitor visitor) {
      return visitor.visitDirectory(this);
      }
    • An interface that defines methods to be implemented by all specific visitors.
    • IVisitor
    • String visitAudioFile(AudioFile file)
    • String visitDirectory(Directory directory)
    • buffer.write(file.accept(this));
    • String visitImageFile(ImageFile file)
    • String visitTextFile(TextFile file)
    • String visitVideoFile(VideoFile file)
    • IVisitor
    • String visitAudioFile(AudioFile file)
    • String visitDirectory(Directory directory)
    • buffer.write(file.accept(this));
    • String visitImageFile(ImageFile file)
    • String visitTextFile(TextFile file)
    • String visitVideoFile(VideoFile file)
    • final List<IVisitor> visitorsList = [
      HumanReadableVisitor(),
      XmlVisitor(),
      ];
    • late final IFile _rootDirectory;
    • _rootDirectory = _buildMediaDirectory();
    • final selectedVisitor = visitorsList[_selectedVisitorIndex];
    • final filesText = _rootDirectory.accept(selectedVisitor);
    • onChanged: _setSelectedVisitorIndex,
    • onPressed: _showFilesDialog,
    • the example widget does not care about the concrete selected visitor as long as it implements the IVisitor interface.
    • a concept of a "shared object" which could be used in multiple contexts simultaneously, hence reducing the memory usage of your code - Flyweight.
    • Chain of Responsibility (CoR), also known as Chain of Command, is a behavioural design pattern,
    • the Chain of Responsibility design pattern is an ordered list of message handlers that know how to do two things
    • process a specific type of message
    • pass the message along to the next message handler.
    • Handler
    • BaseHandler
    • ConcreteHandlers
    • Client
    • The Chain of Responsibility design pattern should be used when the system is expected to process different kinds of requests in various ways, but neither the request types nor the handling sequence is defined at compile time.
    • Furthermore, the CoR pattern should be used when a single request must be handled by multiple handlers, usually in a particular order
    • one thing to remember - the receipt isn't guaranteed. Since CoR introduces the loose coupling between sender and receiver, and the request could be handled by any handler in the chain, there is no guarantee that it will be actually handled.
    • final List<LogMessage> _logs = [];
    • final StreamController<List<LogMessage>> _logStream =
      StreamController<List<LogMessage>>();
    • StreamSink<List<LogMessage>> get _inLogStream => _logStream.sink;
    • Stream<List<LogMessage>> get outLogStream => _logStream.stream;
    • _logs.add(logMessage);
    • _inLogStream.add(UnmodifiableListView(_logs));
    • final LogBloc logBloc;
    • final logMessage = LogMessage(logLevel: logLevel, message: message);
    • logBloc.log(logMessage);
    • final LogBloc logBloc;
    • final logMessage = LogMessage(logLevel: logLevel, message: message);
    • logBloc.log(logMessage);
    • _nextLogger?.logMessage(level, message);
    • : super(logLevel: LogLevel.Debug);
    • late ExternalLoggingService externalLoggingService;
    • : externalLoggingService = ExternalLoggingService(logBloc),
      super(logLevel: LogLevel.Info);
    • late MailService mailService;
    • : mailService = MailService(logBloc),
      super(logLevel: LogLevel.Error);
    • final LogBloc logBloc = LogBloc();
    • late final LoggerBase logger;
    • logger = DebugLogger(
      logBloc,
      nextLogger: InfoLogger(
      logBloc,
      nextLogger: ErrorLogger(logBloc),
      ),
      );
    • onPressed: () => logger.logDebug(randomLog),
    • onPressed: () => logger.logInfo(randomLog),
    • onPressed: () => logger.logError(randomLog),
    • stream: logBloc.outLogStream,
    • snapshot
    • logMessages: snapshot.data!
    • the sender (client) and receiver (logger) are decoupled, and the loggers' chain itself could be built at run-time in any order or structure e.g. you can skip the Debug logger for non-local environments and only use the Info -> Error chain.

Posted from Diigo. The rest of my favorite links are here.

댓글

이 블로그의 인기 게시물

Publish to my blog (weekly)

Publish to my blog (weekly)