Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Design Pattern to use to implement transaction or chaining mechanism

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!

like image 286
Jacobian Avatar asked Nov 08 '15 12:11

Jacobian


People also ask

Which pattern should be used for file system implementation?

File System implementations use the composite design pattern as described previously.

Which among the following are examples of chain of responsibility pattern?

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.

What are the 3 common design patterns groups?

Design Patterns are categorized mainly into three categories: Creational Design Pattern, Structural Design Pattern, and Behavioral Design Pattern.


2 Answers

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.

like image 89
Matías Fidemraizer Avatar answered Oct 13 '22 23:10

Matías Fidemraizer


Composite pattern is an obvious choice for situations when you model a part-whole system. Here is how the diagram of the pattern looks:

Composite pattern

Given that you have a factory producing objects of the same interface, you are almost done implementing the composite pattern.

  • Your factory produces objects conforming to some interface. This interface is the component interface of your composite implementation.
  • Your factory produces concrete classes, which represent the 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();
        }
    }
}
like image 45
Sergey Kalinichenko Avatar answered Oct 13 '22 23:10

Sergey Kalinichenko