Should I (and how to) avoid "forests" of listeners in nested OOP structure.

2 vues (au cours des 30 derniers jours)
Cedric
Cedric le 18 Déc 2017
Modifié(e) : Cedric le 19 Déc 2017
Dear all,
System < handle, with properties System.grids and System.result
Grid < handle, with property Grid.layers
Layer < handle, with property Layer.gridCells
GridCell < handle, with property GridCell.area
where each class implements a property that is a cell array of objects of the class "below", i.e. System.grids={Grid obj #1,..}, Grid.layers={Layer obj #1,..} and Layer.gridCells={GridCell obj #1,..}. Property System.result is built/computed for a specific set of grids (and hence layers and grid cells). Its value must therefore be updated each time a grid or one the grids' layer or one of the layers' cell is updated (e.g. the area). EDIT 1 - If:
gc = system.grids{2}.layers{10}.gridCells{15200} ;
the following:
gc.area = 147 ;
should trigger an update of system.result.
In a less nested context, e.g. if updating a grid would be done through a basic set access to System.grids such as:
system.grids{3} = newGrid ;
I could manage triggering the update of result through a setter for the grids property. In a little more nested context, e.g. if layers can be updated without replacing Grid objects, through:
system.grids{3}.layers{1} = newLayer ;
I could set the layers property of Grid observable:
classdef Grid < handle
properties( SetObservable = true )
layers
end
..
an add listeners to the System object bound to each grid layers property and to the 'PostSet' event. Or better, I can define an event 'updated' in each class Grid, Layer, and GridCell, that would back-propagated to the System object through a chain of listeners: EDIT 2017/12/19 @ 19:30 UTC, e.g.:
classdef Grid < Cascadable
properties
layers
end
methods
function obj = Grid()
obj = obj@Cascadable() ;
end
function addLayer( obj, layer )
obj.layers{end+1} = layer ;
addlistener( layer, 'updated', ...
@(src, evnt) eventHandler_updated( obj, src, evnt )) ;
obj.eventHandler_updated() ;
end
end
end
with
classdef Cascadable < handle
events
updated
end
methods
function obj = Cascadable()
end
function eventHandler_updated( obj, varargin )
fprintf( '%s updated\n', class( obj )) ;
obj.notify( 'updated' ) ;
end
end
end
and an event handler in System that does a little more work, e.g. recomputing result.
While this last approach seems to be "clean enough", it requires adding setters that call NOTIFY for all relevant properties in each class, or overloading SUBSASGN for that purpose, or defining 'PostSet' listeners for all relevant properties of "self" (just for avoiding implementing a lot a setters and instead defining a single event handling method for all properties). This seems to be cumbersome and to defeat the purpose of events/listeners.
Is there a cleaner way? Did I miss an important mechanism, like a 'CascadedPostSet' event?
Cheers,
Cedric

Réponses (0)

Catégories

En savoir plus sur Deploy to C++ Applications Using MATLAB Data API (C++11) dans Help Center et File Exchange

Produits

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by