Design pattern for default implementation with empty methods

帅比萌擦擦* 提交于 2019-12-03 01:27:46
dfa

There are no design patterns for default implementation.

I usually append DoNothing prefix to the name of class. Depending on it's intent I use also Base or Default (the latter is widely used). Probably MouseAdapter should be called DefaultMouseListener.

In the case you care, you can stub systematically an interface with a simple DynamicProxy, you must return only a "nice" default value (null for Object, 0 for numeric, etc).

BTW this is a very good question.

EDIT

Furthermore this is neither a Stub or a Mock: maybe it can be confused with a Stub but the intent is different.

Aditya W

You should follow different design principle : interface-segregation principle

The Interface Segregation Principle states that clients should not be forced to implement interfaces they don't use. Instead of one fat interface many small interfaces are preferred based on groups of methods, each one serving one sub module.

You should not implement MORE And you should not implement LESS

Have a look at related SE questions for more details.

The Interface Segregation Principle

Interface Segregation Principle- Program to an interface

JARC

I have seen this design used in spring where they have a class named FlowExecutionListenerAdapter which saves you implementing all the FlowExecutionListener operations.

However, it does sound like the Null Object Pattern too. However I feel it sits better in the Adapter world purely because it changing the behavour of the interface by allowing you only to implement the bit you want...but its a tough one.

I'm sure this question has been asked before?

This sounds similar no? might be worth a read.

It's also used in Swing (WindowAdapter, which implements WindowListener). It's only a convenience adapter, you only have to define 1-2 methods in this way to have a useful windowlistener. This is indeed an instance of the Adapter pattern, also shows the power of the abstract classes. It's even an example to illustrate why multiple implementation inheritance is useful sometimes.

As for the regular Design Patterns, in the Temlate Method you can define hook operations, which may be overriden (unlike abstract methods, which must be), but the default behaviour (usually the NO-OP) is meaningful too.

Great question.

I have started using NoOp as a class name prefix for this pattern. It's short, clear, and not overloaded (like Empty [contains nothing?], Null [Null Object pattern, which is different?], Abstract [Does it provide some implementation?], or Base [Does it provide some implementation?]).

I may write this style of class when I have a third-party API which provides "Hooks" for isntrumentation during a complex operation. Consider the following two classes provided by a library:

public class LongRunningActionRunner {
    public void runSomethingLong(DecisionListener cdh) {
        // ...
    }
}

public interface DecisionListener {
    public void beforeFooHook();
    public void afterFooHook();
    public void beforeBarHook();
    public void afterBarHook();
    public void beforeBazHook();
    public void afterBazHook();
}

In this case, you might right a class using this pattern like this:

public class NoOpDecisionListener implements DecisionListener {
    @Override public Something beforeFooHook() {}
    @Override public Something afterFooHook() {}
    @Override public Something beforeBarHook() {}
    @Override public Something afterBarHook() {}
    @Override public Something beforeBazHook() {}
    @Override public Something afterBazHook() {}
}

This pattern was prevalent in older versions of Java. It is the Java 7 alternative to default methods in interfaces.

Josh Bloch calls it a skeletal implementation. While a skeletal implementation is typically abstract, you needn't force clients to create a subclass if the skeleton itself is sufficient.

I agree with the previous answer pointing out the Interface Segregation Principle. The need for a skeletal implementation can be a code smell indicating an interface is too "fat" and may be trying to do more than one job. Splitting up the interface is preferable in this scenario to creating a skeletal implementation with dummy or noop logic.

To me this seems closest to the Special Case or Null Object pattern.

Your updates suggest something similar to Template Method expect that you don't have a single method that calls each template method e.g.

public void doEverything()
{
  doThis();
  doThat();
  done();
}

Are you asking about the Null Object Pattern?

Further to your edit, the MyClass object is nothing more than a default implemenation. I don't think there's any particular design pattern that describes it.

I believe Martin Fowler would call this a null object pattern. In his Refactoring book[1], Martin introduces null objects as such:

The essence of polymorphism is that instead of asking an object what type it is and then invoking some behavior based on the answer, you just invoke the behavior. The object, depending on its type, does the right thing. One of the less intuitive places to do this is where you have a null value in a field.

He later adds, "You benefit when many clients want to do the same thing; they can simply rely on the default null behavior." He also introduces an isNull() method for clients requiring variant behaviors.

I would agree that I sometimes see a (often abstract) implementation called an adapter. For example, in the Android framework, AnimatorListenerAdapter (source code here) is described as:

This adapter class provides empty implementations of the methods from Animator.AnimatorListener. Any custom listener that cares only about a subset of the methods of this listener can simply subclass this adapter class instead of implementing the interface directly.

[1] "Refactoring: Improving the Design of Existing Code," Chapter 9, "Simplifying Conditional Expressions," "Introduce Null Object."

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!