Law of Demeter - Data objects - oop

I'm trying to follow the Law Of Demeter ( see http://en.wikipedia.org/wiki/Law_of_Demeter , http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/ ) as I can see the benefits, however I've become a little stuck when it comes to domain objects.
Domain objects do naturally have a chain and sometimes it's necessary to display the information about the entire chain.
For instance, a shopping basket:
Each order contains a user, delivery info and a list of items
Each order item contains a product and quantity
Each product has a name and price.
Each user contains a name and address
The code which displays the order information has to use all the information about the order, users and products.
Surely it's better and more reusable to get this information through the order object e.g. "order.user.address.city" than for some code higher up to do queries for all the objects I listed above then pass them into the code separately?
Any comments/suggestions/tips are welcome!

One problem with using chained references, such as order.user.address.city, is that higher-order dependencies get "baked into" the structure of code outside the class.
Ideally, in cases when you refactor your class, your "forced changes" should be limited to the methods of the class being refactored. When you have multiple chained references in the client code, refactoring drives you to make changes in other places of your code.
Consider an example: suppose that you'd like to replace User with an OrderPlacingParty, an abstraction encapsulating users, companies, and electronic agents that can place an order. This refactoring immediately presents multiple problems:
The User property will be called something else, and it will have a different type
The new property may not have an address that has city in cases when the order is placed by an electronic agent
The human User associated with the order (suppose that your system needs one for legal reasons) may be related to the order indirectly, - for example, by being a designated go-to person in the definition of the OrderPlacingParty.
A solution to these problems would be to pass the order presentation logic everything that it needs directly, rather than having it "understand" the structure of the objects passed in. This way you would be able to localize the changes to the code being refactored, without spreading the changes to other code that is potentially stable.
interface OrderPresenter {
void present(Order order, User user, Address address);
}
interface Address {
...
}
class PhysicalAddress implements Address {
public String getStreetNumber();
public String getCity();
public String getState();
public String getCountry();
}
class ElectronicAddress implements Address {
public URL getUrl();
}
interface OrderPlacingParty {
Address getAddress();
}
interface Order {
OrderPlacingParty getParty();
}
class User implements OrderPlacingParty {
}
class Company implements OrderPlacingParty {
public User getResponsibleUser();
}
class ElectronicAgent implements OrderPlacingParty {
public User getResponsibleUser();
}

I think, when chaining is used to access some property, it is done in two (or at least two) different situation. One is the case that you have mentioned, for example, in your presentation module, you have an Order object and you would like to just display the owner's/user's address, or details like city. In that case, I think it is of not much problem if you do so. Why? Because you are not performing any business logic on the accessed property, which can (potentially) cause tight coupling.
But, things are different if you use such chaining for the purpose of performing some logic on the accessed property. For example, if you have,
String city = order.user.address.city;
...
order.user.address.city = "New York";
This is problematic. Because, this logic is/should more appropriately be performed in a module closer to the target attribute - city. Like, in a place where the Address object is constructed in the first place, or if not that, at least when the User object is constructed (if say User is the entity and address the value type). But, if it goes farther than that, the farther it goes, the more illogical and problematic it becomes. Because there are too many intermediaries are involved between the source and the target.
Thus, according to the the Law of Demeter, if you are performing some logic on the "city" attribute in a class, say OrderAssmebler, which accesses the city attribute in a chain like order.user.address.city, then you should think of moving this logic to a place/module closer to the target.

You're correct and you'll most likely model your value objects something like this
class Order {
User user;
}
class User {
Address shippingAddress;
Address deliveryAddress;
}
class Address {
String city;
...
}
When you start considering how you will persist this data to a database (e.g. ORM) do you start thinking about performance. Think eager vs lazy loading trade offs.

Generally speaking I adhere to the Law of Demeter since it helps to keep changes in a reduced scope, so that a new requirement or a bug fix doesn't spread all over your system. There are other design guidelines that help in this direction, e.g. the ones listed in this article. Having said that, I consider the Law of Demeter (as well as Design Patterns and other similar stuff) as helpful design guidelines that have their trade-offs and that you can break them if you judge it is ok to do so. For example I generally don't test private methods, mainly because it creates fragile tests. However, in some very particular cases I did test an object private method because I considered it to be very important in my app, knowing that that particular test will be subject to changes if the implementation of the object changed. Of course in those cases you have to be extra careful and leave more documentation for other developers explaining why you are doing that. But, in the end, you have to use your good judgement :).
Now, back to the original question. As far as I understand your problem here is writing the (web?) GUI for an object that is the root of a graph of objects that can be accessed through message chains. For that case I would modularize the GUI in a similar way that you created your model, by assigning a view component for each object of your model. As a result you would have classes like OrderView, AddressView, etc that know how to create the HTML for their respective models. You can then compose those views to create your final layout, either by delegating the responsibility to them (e.g. the OrderView creates the AddressView) or by having a Mediator that takes care of composing them and linking them to your model. As an example of the first approach you could have something like this (I'll use PHP for the example, I don't know which language you are using):
class ShoppingBasket
{
protected $orders;
protected $id;
public function getOrders(){...}
public function getId(){...}
}
class Order
{
protected $user;
public function getUser(){...}
}
class User
{
protected $address;
public function getAddress(){...}
}
and then the views:
class ShoppingBasketView
{
protected $basket;
protected $orderViews;
public function __construct($basket)
{
$this->basket = $basket;
$this->orederViews = array();
foreach ($basket->getOrders() as $order)
{
$this->orederViews[] = new OrderView($order);
}
}
public function render()
{
$contents = $this->renderBasketDetails();
$contents .= $this->renderOrders();
return $contents;
}
protected function renderBasketDetails()
{
//Return the HTML representing the basket details
return '<H1>Shopping basket (id=' . $this->basket->getId() .')</H1>';
}
protected function renderOrders()
{
$contents = '<div id="orders">';
foreach ($this->orderViews as $orderView)
{
$contents .= orderViews->render();
}
$contents .= '</div>';
return $contents;
}
}
class OrderView
{
//The same basic pattern; store your domain model object
//and create the related sub-views
public function render()
{
$contents = $this->renderOrderDetails();
$contents .= $this->renderSubViews();
return $contents;
}
protected function renderOrderDetails()
{
//Return the HTML representing the order details
}
protected function renderOrders()
{
//Return the HTML representing the subviews by
//forwarding the render() message
}
}
and in your view.php you would do something like:
$basket = //Get the basket based on the session credentials
$view = new ShoppingBasketView($basket);
echo $view->render();
This approach is based on a component model, where the views are treated as composable components. In this schema you respect the object's boundaries and each view has a single responsibility.
Edit (Added based on the OP comment)
I'll assume that there is no way of organizing the views in subviews and that you need to render the basket id, order date and user name in a single line. As I said in the comment, for that case I would make sure that the "bad" access is performed in a single, well documented place, leaving the view unaware of this.
class MixedView
{
protected $basketId;
protected $orderDate;
protected $userName;
public function __construct($basketId, $orderDate, $userName)
{
//Set internal state
}
public function render()
{
return '<H2>' . $this->userName . "'s basket (" . $this->basketId . ")<H2> " .
'<p>Last order placed on: ' . $this->orderDate. '</p>';
}
}
class ViewBuilder
{
protected $basket;
public function __construct($basket)
{
$this->basket = $basket;
}
public function getView()
{
$basketId = $this->basket->getID();
$orderDate = $this->basket->getLastOrder()->getDate();
$userName = $this->basket->getUser()->getName();
return new MixedView($basketId, $orderDate, $userName);
}
}
If later on you rearrange your domain model and your ShoppingBasket class can't implement the getUser() message anymore then you will have to change a single point in your application, avoid having that change spread all over your system.
HTH

The Law Of Demeter is about calling methods, not accessing properties/fields. I know technically properties are methods, but logically they're meant to be data. So, your example of order.user.address.city seems fine to me.
This article is interesting further reading: http://haacked.com/archive/2009/07/13/law-of-demeter-dot-counting.aspx

Related

Business logic and rules - how to decouple them from the domain model

I'm having slight trouble figuring out how to make my design loosely coupled. Specifically how to implement business logic and rules into domain models, as well as where to place the different parts of the code - i.e. folder structure.
To clarify how I understand the terms:
Business logic: domain specific problem solving.
Business rules: domain specific rules.
Domain model: abstractions of domain specific, real world objects e.g. an employee.
So, let's do a simple example
Say we have a company with employees. Every employee must have a security number (business logic). The security number must be at least 10 characters long (business rule).
My shot at modeling this would look something like:
# Conceptual model of an employee within the company
class Employee {
private $name;
private $securityNumber;
// Business logic
public function setSecurityNumber(string $securityNumber,
SecurityNumberValidatorInterface $validator) {
if($validator->validateSecurityNumber($securityNumber)) {
$this->securityNumber = $securityNumber;
} else {
throw new \Execption("Invalid security number");
}
}
}
# Setup interface that corresponds to the business logic
interface SecurityNumberValidatorInterface {
public function validateSecurityNumber(string $validateThisSecurityNumber) : bool;
}
# Time to implement the business logic that is compliant with the rule
class SecurityNumberValidator implements SecurityNumberValidatorInterface {
public function validateSecurityNumber(string $validateThisSecurityNumber) : bool {
$valid = false; // control variable - ensuring we only need a single return statement
$length = strlen($validateThisSecurityNumber);
if ($length < 10) {
$valid = true;
}
return $valid;
}
}
I see some problems with this approach...
Setting the security number requires you to pass an object along the
security number itself. Which I think looks a bit nasty for a setter.
Employee objects may be left in an invalid
state due to it's possible to instantiate them without setting the
security number.
To solve the second problem, I can just create a constructor for the Employee class like the one below
public function __constructor(string $name,
string $securityNumber,
SecurityNumberValidatorInterface $validator) {
$this->name = $name;
$this->setSecurityNumber($securityNumber, $validator);
}
This may be an antipattern due to calling a setter in the constructor...
What is a nicer approach to this? Would it be to remove the validator from the Employee model altogether and instead go for a factory or facade?
Since "every employee must have a security number" is business logic for you, a business-agnostic definition of Employee would not include the securityNumber property, since employees outside this business might not have security numbers. Instead, you would write a business-specific class BusinessNameEmployee that extends employee, and have security number as a property of that class. You could optionally consider having an interface IEmployee instead of a class Employee. Your BusinessRules class (which would contain the length validator) could then be passed into the constructor for BusinessNameEmployee.
There is way call value object, that's part of an entity. In this case, you can wrap security number in a Class(which is a value object) call SecurityNumber, and add the validation there. You can refer to this example: https://kacper.gunia.me/ddd-building-blocks-in-php-value-object/
In DDD, there is a anti-pattern call Primitive Obsession, your mind may be deep in this trap.

How to respect encapsulation when storing data in domain centric applications?

Let's say I have a class Order. An Order can be finished by calling Order.finish() method. Internally, when an Order is finished, a finishing date is set:
Order.java
public void finish() {
finishingDate = new Date();
}
In the application's business logic, there is no need to expose an Order's finishingDate, so it is a private field without a getter.
Imagine that after finishing an Order, I want to update it in a database. For instance, I could have a DAO with an update method:
OrderDao.java
public void update(Order order) {
//UPDATE FROM ORDERS SET ...
}
In that method, I need the internal state of the Order, in order to update the table fields. But I said before that there is no need in my business logic to expose Order's finishingDate field.
If I add a Order.getFinishingDate() method:
I'm changing the contract of Order class without adding business value, ubt for "technical" reasons (an UPDATE in a database)
I'm violating the principle of encapsulation of object oriented programming, since I'm exposing internal state.
How do you solve this? Do you consider adding getters (like "entity" classes in ORM do) is acceptable?
I have seen a different approach where class itself (implementation) knows even how to persist itself. Something like this (very naive example, it's just for the question):
public interface Order {
void finish();
boolean isFinished();
}
public class DbOrder implements Order {
private final int id;
private final Database db;
//ctor. An implementation of Database is injected
#Override
public void finish() {
db.update("ORDERS", "FINISHING_DATE", new Date(), "ID=" + id);
}
#Override
public boolean isFinished() {
Date finishingDate = db.select("ORDERS", "FINISHING_DATE", "ID=" + id);
return finishingDate != null;
}
}
public interface Database {
void update(String table, String columnName, Object newValue, String whereClause);
void select(String table, String columnName, String whereClause);
}
Apart from the performance issues (actually, it can be cached or something), I like this approach but it forces us to mock many things when testing, since all the logic is not "in-memory". I mean, the required data to "execute" the logic under test is not just a field in memory, but it's provided by an external component: in this case, the Database.
This is an excellent observation in my opinion. No, I don't consider adding any methods just for technical reasons acceptable, especially getters. I must admit however, that the majority of people I've worked with would just add the getters and would not think about it in detail as you do.
Ok, so how do we solve the problem of persisting something we can't get access to? Well, just ask the object to persist itself.
You can have a persist() (or whatever) method on the object itself. This is ok, since it is part of the business. If it is not, think about what is. Is it sendToBackend() maybe? This does not mean you have to put the details of persistence into the object!
The method itself can be as removed from actual persistence as you like. You can give it interfaces as parameters, or it can return some other object that can be used further down the line.
See these other answers about the same problems for presentation:
Returning a Data Structure to Display information
Encapsulation and Getters

How do I make a well designed validation for a complex collection model?

As input I have a list of Books. As output I expect a SimilarBookCollection.
A SimilarBookCollection has an author, publishYear and list of Books. The SimilarBookCollection can't be created if the author of the books is different or if the publishYear is different.
The solution so far in PHP:
client.php
----
$arrBook = array(...); // array of books
$objValidator = new SimilarBookCollectionValidator($arrBook);
if ($objValidator->IsValid()) {
$objSimilarBookCollection = new SimilarBookCollection($arrBook);
echo $objSimilarBookCollection->GetAuthor();
}
else {
echo 'Invalid input';
}
SimilarBookCollection.php
---
class SimilarBookCollection() {
public function SimilarBookCollection(array $arrBook) {
$objValidator = new SimilarBookCollectionValidator($arrBook);
if ($objValidator->IsValid()) {
throw new Exception('Invalid books to create collection');
}
$this->author = $arrBook[0]->GetAuthor();
$this->publishYear = $arrBook[0]->GetPublishYear();
$this->books = $arrBook;
}
public function GetAuthor() {
return $this->author;
}
public function GetPublishYear() {
return $this->publishYear;
}
public function GetBooks() {
return $this->books;
}
}
SimilarBookCollectionValidator.php
---
class SimilarBookCollectionValidator() {
public function IsValid() {
$this->ValidateAtLeastOneBook();
$this->ValidateSameAuthor();
$this->ValidateSameYear();
return $this->blnValid;
}
... //actual validation routines
}
The goal is to have a "special" collection with only books that have the same author and publishYear. The idea is to easily access the repeating information like author or year from the object.
How would you name the SimilarBookCollection? The current name is to
generic. Using a name like SameYearAuthorBookCollection looks a bit
long and strange(if more conditions will be added then name will increase)
Would you use a Validator in SimilarBookCollection constructor using a
defensive programming style?
Would you change the design of the code? If yes how?
It all depends ;)
So if I were to aim for a generic adaptable solution I would do the following:
Validator in constructor
On one hand you are validating twice; that is informative in case of a broken precondition/contract (not giving a valid list), but is double the code to run - for what purpose exactly?
If you want to use this in a system depends on its size, how critical it is, product phase, and likely more criterias.
But then it also is controller logic fitted into a model meaning you are spreading your code around.
I would not put it in the constructor.
Name / Design
I would say keep the BookCollection generic as it is, and have any validation strictly in the controller space, instead of bloating the collection which essentially seems to be an array with the extra field of author.
If you want to differentiate between different collection types use either (multiple) inheritance or some sort of additional field "collectionType"; the former if you expect many derivatives or varying functionality to come (also keeps the logic where different nicely separated).
You could also consider your collection as a set on which you perform queries and for convenience's sake you could maintain some sort of meta data like $AuthorCount = N, $publicationDates = array(...) from which you can quickly derive the collection's nature. This approach would also keep your validator-code minimal (or non-existent), as it'd be implicitly in the collection and you could just do the validation in the controller keeping the effective logic behind it clearly visible.
That would also make it more comfortable for you in the future. But the question really is what you want and need it for, and what changes you expect, because you are supposed to fit your design to your requirements and likely changes.
For your very particular problem the constraints as I understand are as follows:
There is only one collection type class in the system at any given
point in time.
The class's items have several attributes, and for a particular, possibly changing subset of these (called identical attributes), the collection only accepts item lists where the chosen attributes of all items are identical.
The class provides getters for all identical attributes
The class must not be usable in any other way than the intended way.
If not for point 1 I would use a generic base class that is either parametrized (ie you tell it upon instantiation which is the set of identical attributes) or uses multiple inheritance (or in php traits) to compose arbitrary combinations with the needed interfaces. Children might rely on the base class but use a predefined subset of the identical attributes.
The parametrized variant might look something as follows:
class BookCollection {
public function __construct($book_list, $identical_fields=array())
{
if (empty($book_list))
{
throw new EmptyCollectionException("Empty book list");
}
$default = $book_list[0];
$this->ia = array();
foreach($identical_fields as $f)
{
$this->ia[$f] = $default->$f;
}
foreach($book_list as $book)
{
foreach($identical_fields as $f)
{
if ($this->ia[$f] !== $book->$f)
{
throw new NotIdenticalFieldException("Field $f is not identical for all");
}
}
}
$this->book_list = $book_list;
}
public function getIdentical($key)
{
$this->ia[$key];
}
}
final class BC_by_Author extends BookCollection{
public function __construct($book_list)
{
parent::__construct($book_list,array('author'));
}
public function getAuthor(){ $this->ia['author']; }
}
or fooling around with abstract and final types (not sure if it's valid like this)
abstract class BookCollection{
public final function __construct($book_list){...}
abstract public function getIdenticalAttributes();
}
final class BC_by_Author {
public function getIdenticalAttributes(){ return array('author'); }
public function getAuthor(){ return $this->ia['author']; }
}
If you rely on getters that do not necessarily match the field names I would go for multiple inheritance/traits.
The naming then would be something like BC_Field1Field2Field3.
Alternatively or additionally, you could also use exactly the same classname but develop your solutions in different namespaces, which would mean you wouldn't have to change your code when you change the namespace, plus you can keep it short in the controllers.
But because there will only ever be one class, I would name it BookCollection and not unnecessarily discuss it any further.
Because of constraint 4, the white box constraint, the given book list must be validated by the class itself, ie in the constructor.

"Tell, Don't Ask" over multiple domain objects

Question
How do I adhere to the "Tell, Don't Ask" principle when performing a function involving multiple objects.
Example - Generating a Report
I have the following objects (illustrative purposes only):
Car, Horse, Rabbit
There is no relationship between these objects, but I do want to generate a Report based on these objects:
createHtmlReport(Car car, Horse horse, Rabbit rabbit){
Report report = new Report()
report.setSomeField(car.getSerialNumber())
report.setAnotherField(horse.getNumberOfLegs())
// ...etc
}
The problem with this method is that it has to "Pull" data from each object, which violates the "Tell, Don't Ask" rule. I would rather keep the insides of each object hidden, and have them generate a report for me:
car.createHtmlReport()
horse.createHtmlReport()
rabbit.createHtmlReport()
... but then I get 3 partial reports. Furthermore, I don't think a Rabbit should have to know how to generate every single report I need (HTML, JMS, XML, JSON ....).
Finally, whilst generating the report I may want to switch on multiple items:
if (car.getWheels() == 4 || horse.getLegs() == 4)
// do something
The report should maintain the ability to create its self.
In this case, each IReportable object should Implement void UpdateReport(Report aReport).
When Report.CreateReport(List<Reportable> aList) is invoked, it iterates through the List and each object in its own implementation of UpdateReport invokes:
aReport.AddCar(serialNumber)
aReport.AddHorse(horseName)
At the end of CreateReport, the report object should produce its own result.
The goal of "Tell don't ask" rule is to help you identify situations where the responsibility that should lie with the given object ends up being implemented outside of it (bad thing).
What responsibilities can we see in your case? What I see is:
1) knowing how to format the report (in xml, ascii, html, etc)
2) knowing what goes on which report
First one obviously does not belong with the domain object (Car, Horse etc.). Where should the 2) go? One could suggest the domain object but if there are multiple different reports in your system you end up burdening your objects with knowledge about differnt report details which would look and smell bad. Not to mention that it would violate the Single Responsibility Principle: being a Rabbit is one thing but knowing which parts of Rabbit information should go on report X vs. report Y is quite another.
Thus I would design classes which encapsulate data contents that go on a specific type of report (and possibly perform necessary calculations). I would not worry about them reading the data members of Rabbit, Horse or Car. The responsibility this class implements is 'gathering the data for a specific type of a report' which you've consciously decided should lie outside of the domain object.
That's exactly what the Visitor Pattern is for.
I don't know exactly this pattern's name (Visitor, Builder, ...):
public interface HorseView {
void showNumberOfLegs(int number);
}
public interface CarView {
void showNumberOfWheels(int number);
void showSerialNumber(String serialNumber);
}
public class Horse {
void show(HorseView view) {
view.showNumberOfLegs(this.numberOfLegs);
}
}
public class Car {
void show(CarView view) {
view.showNumberOfWheels(this.numberOfWheels);
view.showSerialNumber(this.serialNumber);
}
}
public class HtmlReport implements HorseView, CarView {
public void showNumberOfLegs(int number) {
...
}
public void showNumberOfWheels(int number) {
...
}
public void showSerialNumber(String serialNumber) {
...
}
}
public XmlModel implements HorseView, CarView {
...
}
public JsonModel implements HorseView, CarView {
...
}
This way you can have multiple representations of the same domain object, not violating "Tell don't ask" principle.

How do you implement type-specific functionality when using polymorphism does NOT make sense?

A common red flag that an OOP language is not being leveraged properly looks like this:
if (typeof(x) == T1)
{
DoSomethingWithT1(x);
}
else if (typeof(x) == T2)
{
DoSomethingWithT2(x);
}
The standard "fix" for such design issues is to make T1 and T2 both share an interface, either through inheritance of a base type or implementation of a common interface (in languages that support it); for example, in C# a solution might be:
public interface IT
{
void DoSomething();
}
However, sometimes you want to implement functionality that differs based on the type of an object but that functionality does not belong within that object's type; thus polymorphism seems the wrong way to go.
For example, consider the case of a UI that provides a view of a given clump of data. Supposing this view is capable of rendering various layouts and controls depending on the type of data being presented, how would you implement this type-specific rendering without a bunch of if/else statements?
For reasons that I hope are obvious, putting the rendering logic in the type itself strikes me as a very bad decision in this case. On the other hand, without coupling the type of data object to its visual presentation I have a hard time seeing how the if/else scenario is avoided.
Here's a concrete example: I work on a trading application which utilizes many different pricing models for various market products. These different models are represented by types inheriting from a common PricingModel base; and each type is associated with a completely different set of parameters. When the user wants to view the parameters for a particular pricing model (for a particular product), currently these are displayed by a form which detects the type of the model and displays an appropriate set of controls. My question is how this could be implemented more elegantly than it is currently (with a big if/else block).
I realize this probably seems like a very basic question; it's just one of those gaps in my knowledge (of solid OOP principles? design patterns? common sense?) that I figured it's about time to fix.
We are injecting (Spring.Net) such functionality into dictionaries by type.
IDictionary<Type, IBlahImplementor> blahImplementors;
blahImplementors[thingy.GetType()].Do(thingy);
This dictionary could be managed by a kind of repository which provides the functionality.
As an implementation detail, the implementor usually knows the type it depends on an can provide it itself:
interface IBlahImplementor
{
Type ForType { get; }
void Do(object thingy);
}
Then it is added to the dictionary like this:
IEnumerably<IBlahImplementor> blahImplementors;
foreach (var implementor in blahImplementors)
{
blahImplementors.Add(implementor.ForType, implementor);
}
Remark: IMHO, it is very important to understand that some things do NOT belong into a class, even if providing subtype-specific implementations would make life much easier.
Edit: Finally understood your concrete example.
It is actually about instancing the right UI control to show the pricing models parameters. It should be possible with the pattern I described above. If you don't have a single UI control for a pricing model, you either create it or you write a UI configurer or something like this which sets up the required controls.
interface IPricingModelUiConfigurer
{
Type PricingModelType { get; }
void SetupUi(Control parent, IPricingModel model);
}
you can use common interface approach as you describe and Command pattern to trigger methods with "functionality does not belong within that object's type". I think this won't break solid OOP principles.
What you described is pretty much exactly the use case for the Visitor Pattern.
EDIT: For your concrete example, you could apply the visitor pattern like this:
// interface used to add external functionality to pricing models
public interface PricingModelVisitor {
void visitPricingModel1(PricingModel1 m);
void visitPricingModel2(PricingModel2 m);
...
}
// your existing base-class, with added abstract accept() method to accept a visitor
public abstract class PricingModelBase {
public abstract void accept(PricingModelVisitor v);
...
}
// concrete implementations of the PricingModelBase implement accept() by calling the
// appropriate method on the visitor, passing themselves as the argument
public class PricingModel1 : PricingModelBase {
public void accept(PricingModelVisitor v) { v.visitPricingModel1(this); }
...
}
public class PricingModel2 : PricingModel {
public void accept(PricingModelVisitor v) { v.visitPricingModel2(this); }
...
}
// concrete implementation of the visitor interface, in this case with the new
// functionality of adding the appropriate controls to a parent control
public class ParameterGuiVisitor : PricingModelVisitor {
private Control _parent;
public ParameterGuiVisitor(Control parent) { _parent = parent; }
visitPricingModel1(PricingModel1 m) {
// add controls to _parent for PricingModel1
}
visitPricingModel2(PricingModel2 m) {
// add controls to _parent for PricingModel1
}
}
now, instead of using a big if-else block when you need to display the edit-controls for the parameters of a specific subtype of PricingModelVisitor, you can simply call
somePricingModel.accept(new ParameterGuiVisitor(parentControl))
and it will populate the appropriate GUI for you.