简体   繁体   中英

How to design the interface / abstract class here (OOP design)

I have a abstract class and some classes extend the abstract class. Now i wanted to do some preprocessing before every functions present in the child classes ( for example the functions are nothing but fetching entities from DB, so before even going for DB just check the entities in the cache if the entities are present in the cache then return else call to call() or call(final Set<String> args) fetch the entities store it in cache and return ). So i introduced an interface eg

interface PQRCallable <K> {
    K call();
    Set<K> call(final Set<String> args);
} 

Inside the call function the subclass functions writes the logic to fetch the entities from DB. Now every function in the subclasses call either of the two common functions present in the abstract class ie doProcessing(String k, ..., PQRCallable pQRCallable) doProcessing(Set<k>, ..., PQRCallable pQRCallable) with a PQRCallable so that if the preprocessing will face any issue it would fall back to call() or call(final Set<String> args) .

My problem here is that now every functions inside the subclasses will need to implement both the functions. And doProcessing(Set<k>, ..., PQRCallable pQRCallable) will always call Set<K> call(final Set<String> args); and doProcessing(String k, ..., PQRCallable pQRCallable) will always call K call(); . Hence actually the subclass will just implement one function and for other function they should just throw some exception like UnsupportedOperationException .

Do anybody can suggest me a better approach for this. Thanks.

Maybe the pattern decorator can help you to handle that.

Sorry the link is in C# but there is a nice UML schema!

Wrap the doProcessing method :

doProcessing(String k, ...){
    this.pQRCallable.call();
    //Your processing logic
    //It could be useful to catch the UnsupportedOperationException
}

doProcessing(Set<K> k, ...){
    this.pQRCallable.call(args);//you didn't specify how you are getting the args
    //Your processing logic
}

You can see that the pQRCallable is now a field in your abstract class, and you could set it at runtime via utility class or using constructor of the concrete subclasses.

Sub-classes won't have to implement your interface and at runtime you'll be sure that you are setting the right PQRCallable (the one implementing your desired call)

You could wrap your DB methods using Dynamic Proxies. In your Invocation Handler you could check whether the requested objects are in the cache already. Only if they are not in your cache you could forward the call to your actual DB accessing object.
For example code check out: http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html

Consider using a mature data access framework with caching, such as Hibernate second-level cache .

Failing that, your situation fits best into the GoF Template Method pattern. Pay particular attention to the real world example for DataAccessObject .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM