I implemented a simple Factory class in C# and Java. This class builds instances of concrete working classes that have one and the same interface. In particular all these classes have such methods as:
create
select
alter
etc.
Now I want to have a mechanism (built on top of some classical/non-classical Pattern) that will allow me to create "chains" of these methods or to encapsulate them in a kind of transaction. In a pseudo-code I expect to see something like:
Transaction tnx = create(...args...).alter(...args_2...);
//tnx.Execute();
Or something like:
Transaction tnx;
tnx.Start();
tnx.Add(method_name, ... variable list of arguments ...);
tnx.Add(another_method_name, ... variable list of arguments ...);
tnx.Execute();
I'm not that good at design patterns and I'm not sure what pattern to use. I hope someone can share and drop a couple of lines of code (in C# or in Java) that will demonstrate how this can be implemented. Thanks!
File System implementations use the composite design pattern as described previously.
A Chain of Responsibility Pattern says that just "avoid coupling the sender of a request to its receiver by giving multiple objects a chance to handle the request". For example, an ATM uses the Chain of Responsibility design pattern in money giving process.
Design Patterns are categorized mainly into three categories: Creational Design Pattern, Structural Design Pattern, and Behavioral Design Pattern.
Unit of work is the right pattern to represent domain transactions.
It accumulates changes (adds, updates and remove) and they can be atomically accepted or discarded. Atomicity is guaranteed by the implementation of the whole unit of work, and the implementer must be sure that changes are persisted or discarded atomically.
Check how Martin Fowler defines it on his pattern catalog:
Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
A possible interface to Unit of work pattern could be:
public interface IUnitOfWork
{
void Commit();
void Rollback();
}
And you can also add the following methods to the interface:
// Note I've added a generic type parameter to define what kind of
// objects will handle the whole unit of work
public interface IUnitOfWork<TObject>
{
void RegisterNew(TObject some);
void RegisterUpdated(TObject some);
void RegisterDeleted(TObject some);
void Commit();
void Rollback();
}
Anyway, all updates should be handled using a change tracking monitorized by the unit of work, and some adds and deletes too:
If you add a new object to a collection associated to some other object (1-n association), an unit of work should be able to detect that the object is dirty and it should be persisted without manually telling the unit of work to do so.
Same for removes. If you remove an object from an 1-n association and no other object references it (an orphan object) it should be automatically marked as deleted.
Most data mappers like OR/M frameworks already implementing object change tracking using object proxies to intercept property set calls.
Composite pattern is an obvious choice for situations when you model a part-whole system. Here is how the diagram of the pattern looks:
Given that you have a factory producing objects of the same interface, you are almost done implementing the composite pattern.
Leaf
classes in your composite implementation.The only class left for you to build is the Composite
class.
Let's say your Component
interface looks like this:
public interface IComponent {
void Create();
void Alter();
void Execute();
}
Then your composite class Transaction
may look like this:
public class Transaction : IComponent {
private readonly IList<IComponent> components = new List<IComponent>();
public void Add(IComponent c) {
components.Add(c);
}
void Create() {
foreach (var c in components) {
c.Create();
}
}
void Alter() {
foreach (var c in components) {
c.Alter();
}
}
void Execute() {
foreach (var c in components) {
c.Execute();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With