All who have developed a tabbed wizard control know that using a common data object shared between all the tabs is a good design. The refactored design is analogous to this, in addition to employing the Observer pattern. The WinForm user control container module described in Part I is just an advanced, decoupled MVP implementation of a multi-tabbed user interface module.
The refactoring of the module comprises these steps:
1. Extract all common reference data into a new ‘subject’ class as private members.
2. Expose the reference data as public properties.
3. Add event definitions to the applicable properties to notify ‘observers’ of changes to the ‘subject’.
4. Add a property to the presenter to hold an instance of the new BPRD object type.
5. Add a property to the view interface, of the new BPRD object type.
6. Add code in the presenter to create an instance of the reference data (BPRD).
7. Add code in the presenter to set the BPRD property of each of the views.
8. Add event handlers in the presenter and views (observers) to subscribe to applicable notifications from the new BPRD object.
In the new design, all views hold a reference (pointer) to a common, shared instance of the BPRD object. They all change the common object and they all can subscribe to whatever event they need to get notified of. Thus, the presenter need not contain any code to handle BPRD events to then invoke methods on the views. This leads to a much simpler presenter. The views are also somewhat simpler, as the view interface now contains less to implement.
The refactored view interface looks like this:
public interface IEkspederingView
{
//note how all the get/set events from part I are gone
//property pointing to the current common, shared BPRD
EkspederingFellesData GjeldendeEkspederingFellesData{get; set;}
...
}
The new business process reference data class looks like this:
{
public EventHandler<EventArgs> KontonummerSatt;
public string Kontonummer
{
get { return _kontonummer; }
set
{
_kontonummer = value;
//subject: notify subscribers of change
if (KontonummerSatt != null) this.KontonummerSatt(this, new EventArgs());
}
}
private string _kontonummer;
...
}
The presenter looks like this:
public class EkspederingPresenter
{
public EkspederingPresenter()
{
//create and load the BPRD
_currentReferenceData = new EkspederingFellesData();
//add the current BPRD to all the views
_innbetalingView = new InnbetalingView();
_innbetalingView.GjeldendeEkspederingFellesData = _currentReferenceData;
}
public EkspederingFellesData GjeldendeEkspederingFellesData
{
get { return _currentReferenceData; }
}
private EkspederingFellesData _currentReferenceData;
private InnbetalingView _innbetalingView;
...
}
And finally, one of the views looks like this:
public class InnbetalingView : IEkspederingView
{
public InnbetalingView()
{
//observer: add event handlers to subscribe to notifications to BPRD
this.GjeldendeEkspederingFellesData.KontonummerSatt += new EventHandler<EventArgs>(OnKontonummerSatt);
}
public EkspederingFellesData GjeldendeEkspederingFellesData
{
get { ... }
set{...}
}
public void OnKontonummerSatt(object sender, EventArgs e)
{
//do function X13
}
...
}
The reference data value object is the ‘Subject’ of the Observer pattern, while the ‘Observer’ objects are the presenter and (possibly) the views. Thus, the reference data ‘Subject’ object (don’t get confused) is in fact a ‘Model’ object, although not a domain object such as a customer or an order.
If this combination of the observer pattern, the MVP pattern and a reference data object should have a name, I would call it the “Model Reference Data” pattern, the subject/model being the common, shared and observed reference data.
[UPDATE] Martin Fowler has since retired MVP and replaced it with the Supervising Presenter pattern. The new pattern is actually very like our adapted MVP usage, as it fits better with WinForms data binding.
2 comments:
Oh shait! koder dere på *norsk* !?
--larsw
Jepp, kunden ville ikke oversette sine domene-termer til engelsk (bank/finans), og siden vi bare bidrar med "kjøtt" på prosjektet, så bøyer vi oss for dem (a.k.a konsulenter) =D
Post a Comment