I'm redesigning an old legacy humongous product and I'd like to get an input about my design:
In the product I have GUI, hardware, about 15 logic objects, many commands that path between all the objects and a configuration file.
The design must include: simulation mode, tests, agile style, low coupling between objects, error handling, parallel programing, hidden password protected code and good documentation with maybe UML design.
The software is backward compatible and each user might want to use any version he decides to and the logic will decided which version of each single implementation of any method in the software will run (the newest possible according to the user's hardware and license configuration combination).
Currently the user runs the exe that checks for the config file we gave the user (contains what hardware combination he got and which parts of the program he is allowed to use) and then the correct factory of all the objects is created and the objects are being initialized. Most objects are singleton and particularly the hardware objects. The abstract factory creates different types of the whole system, thus, the created factory handles all the initializations and the different kinds of the same object are not redirected to be initialized through the factory. The hardware is handled through single element queues and self addressed envelopes.
beside wondering if by now it all seems ok, my question is:
Each object writes and reads a bit differently to the hardware. I maid the hardware side drivers with a common use through an interface. How should I implement the command design pattern in this case?
I wanted the logic of how to write from a specific object to a specific hardware to be encapsulated within a command yet the command design pattern, as I understand it, receives an empty request run() with no parameters while in my case each object needs to send this logic different parameters.
I didn't want to have each object contain his own version of write since I want inheritance relationship between the different version for easy maintainability in the future. If there is a bug in one version I want all the children of that version to be auto corrected or that I at least will know who should be changed.
Thus, the solution I had in mind was:
The write method (for example) in each object will inherit from the specific write method that inherits from command. All those methods will send 2 fields: the name of the object that is requesting the command and a string that can be parsed with all the parameters this specific "write" needs to pass. The command will hold a queue of the requests (which will be organized with chain of responsibility, priority and threads), parse the data and send it to the handling specific "write" method without the first object knowing who the second object that handles the command is (for low coupling). If the handling object has a response then it will be passed back either by another command or by an event that the first requesting object is listening for.
I see only benefits to this design and the only drawback is that when I use "write" in the first object I have to pass a long list of information.
I hope you understood my question,
thanks in advance,
d 0_o b
Design patterns are not set in stone. You modify the idiom to fit the need.
However for that pattern each action is wrapped as a command. Thus you could create the command instance with the parameters via the ctor. Then the generic method to executes the command without parameters.
The write method (for example) in each object will inherit from the specific write method that inherits from command
That has nothing to do with patterns.
And it is a bad idea.
You use inheritance to represent an 'is' relationship. Common functionality is not a reason. Composition provides that.
Also you didn't explain what 'write' does, but it suggests a different logical functional level. Thus a better design for larger systems is to implement an actual layer which consumes other objects. Thus given Command A the functional layer would consume an instance of A and do the 'write'. The equivalence here would be a database layer or a printer/display layer. The complexity of such layers justify the layer where similar functionality might not.