Design pattern / use of an approach in which actions on an object occur through closure pass the instance itself

I saw an intriguing approach to the problem here Mauricio Linares .

Add the lock directly to this DataObject, you can define it like this:

public class DataObject { private Lock lock = new ReentrantLock(); public void lock() { this.lock.lock(); } public void unlock() { this.lock.unlock(); } public void doWithAction( DataObjectAction action ) { this.lock(); try { action.doWithLock( this ) : } finally { this.unlock(); } } // other methods here } public interface DataObjectAction { void doWithLock( DataObject object ); } 

And when using it, you can simply do it like this:

 DataObject object = // something here object.doWithAction( new DataObjectAction() { public void doWithLock( DataObject object ) { object.setProperty( "Setting the value inside a locked object"); } } ); 

I would not think of such a solution in which actions on an object are processed through a closure to which an instance of itself is passed (this).

Does this follow the design pattern?

Are there any other common customs? I can imagine the security lock associated with EDT and ensure that resources are closed in an attempt / finally.

It would be useful to evaluate new applications of this approach, so I can add it to my toolbar.

+6
source share
2 answers

This is the Execute Around Method idiom (see the template repository and this SO question ). It is very related to the strategy template. This particular example also uses the low-level Double Dispatch pattern.

I'm not sure when it was first described as an OOP pattern, but probably in KentBeck's Smalltalk Best Practice Patterns. It was probably used in LISP before, although I have no evidence of this from my head.

The executed Around method is an abstraction around try ... catch ... finally and is used when you have something that needs to be done after a block of code. Resource management is a typical example: fixing or rolling back transactions , releasing locks and mutexes , closing files and sockets , etc.

Usually you find the idiom used with closure , as in the second example. Smalltalk and Ruby are stars using this idiom where it is visible everywhere.

Some languages ​​are starting to build syntactic sugar around this pattern. Python has context managers "; C # has a using statement; Java 7 has a try with a resource . In languages ​​with destructors (C ++ / D), the associated idiom is Resource Assquisition Is Initilation (RAII) . D also has Scope Guard>, which are also with one abstraction around try ... catch ... finally .


Update

Besides managing resources, this is useful when you need to do common things around a call or during an iteration.

Spring -JDBC uses it for abstract iteration on request: see RowMapper, RowCallbackHandler, and ResultSetExtractor

JDK uses pattern to perform privileged actions

You can use it in a stopwatch implementation.

I even saw that it was used with registered hooks to do unrelated things around a block of code. For example: write the state to the database, record the results, the runtime of the log and plan the next action.

+2
source

This is not just closing an anonymous class .

0
source

Source: https://habr.com/ru/post/897584/


All Articles