Should I (and how to) avoid "forests" of listeners in nested OOP structure.
    3 Ansichten (letzte 30 Tage)
  
       Ältere Kommentare anzeigen
    
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
0 Kommentare
Antworten (0)
Siehe auch
Kategorien
				Mehr zu Historical Contests finden Sie in Help Center und File Exchange
			
	Produkte
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
