preface

Only a bald head can be strong

To recap:

  • Explain the agency model to your girlfriend

The previous article has explained the proxy pattern, today is going to explain the decoration pattern ~

FilterInputStream = FilterOutputStream = FilterInputStream = FilterOutputStream = FilterInputStream

In fact, both the proxy mode and the decoration mode. Essentially I think it’s a way of enhancing an existing object

So let’s get started. If there are any mistakes in this article, please feel free to correct them in the comments section

Disclainer: This article uses JDK1.8

Common methods of object enhancement

Many times we may not be satisfied with the objects that Java provides to us and do not meet our functionality. At this point we want to enhance the Java original object, can achieve what we want to be good ~

In general, object enhancement can be implemented in three ways:

  • inheritance
    • Inheriting parent class, extending child class
  • Decorator mode
    • Use “wrapping” to enhance objects
  • The proxy pattern
    • Explain to your girlfriend the agency model

1.1 inheritance

The simplest way to do this is to inherit from the parent class and extend the child class. Although simple, this approach has major drawbacks:

  • If the parent class has data, information, and attributes, then the child class cannot be enhanced.
  • Second, the requirements cannot be changed after the subclass is implemented, and the enhanced content is fixed.

1.1.1 the first point

The first point takes the previous JDBC learning time:

  • I wanted to write a simple JDBC connection pool by myselfList<Connection>To manage. Obviously our object is Connection when writing toclose()I’m stuck in the method.
  • Because the function we want is: callclose()Let our Connection return to the “Connection pool” (collection), not close it.
  • At this point weCan’tThe enhancement is achieved by inheriting from the parent class. Because the Connection object is implemented by the database vendor, various information is bound to the Connection object (username, password for the database, what the specific database is, and so on). weSubclasses that inherit Connection cannot get the corresponding data! Let alone callclose()Methods.

1.1.2 the second point

Let me give you an example of my second point:

Now I design a phone class:


public class Phone {
    // You can make calls
    public void call(a) {
        System.out.println("Call around and follow the public account Java3y."); }}Copy the code

At this point, I want to be able to listen to the ring back tone before making a Phone call, so I inherit the Phone class to achieve what I want.


public class MusicPhone extends Phone {
    
    : / / listen to
    public void listenMusic(a) {
        System.out.println("I miss is no words don't say, I miss is dreaming together ~~~~~~");
    }

    @Override
    public void call(a) {

        // Listen to the ringtone before making a phone call
        listenMusic();

        super.call(); }}Copy the code

Our function is ready:

  • At this point, I suddenly want to fulfill one more requirement, I want to listen to the phone and tell me the current time. Ok, let’s inherit it to enhance it:

// This inherits the MusicPhone class
public class GiveCurrentTimePhone extends MusicPhone {

    // Give the current time
    public void currentTime(a) {
        System.out.println("The current time is:" + System.currentTimeMillis());
    }

    @Override
    public void call(a) {
        super.call();

        // What time is it nowcurrentTime(); }}Copy the code

So we can still get the job done:

But now I want to change:

  • I don’t want to listen to the ring back tone, just want to listen to the phone notice time is good…….. But our notification time phone class is inherited from the ring back Tone phone class.
  • I might: I want to report the time before I listen to the phone, listen to the music after the phone! .
  • If the requirements change a lot, and we implement them by inheritance, this will cause a phenomenon: class explosion! And the level of inheritance may be more ~

Therefore, we can see that the subclass inherits the parent class in this way to extend is very limited, inflexible ~

So we have decoration mode!

1.2 Decoration Mode

First let’s look at how the decoration mode is used.

1.2.1 Prerequisite code

Telephone interface:


// A good design is abstracted into interfaces or abstract classes
public interface Phone {

    // You can make calls
    void call(a);
}

Copy the code

Specific implementation:


public class IphoneX implements Phone {


    @Override
    public void call(a) {
        System.out.println("Call around and follow the public account Java3y."); }}Copy the code

1.2.2 Implementation of packaging mode

Above we have an interface and a default implementation. The packaging pattern looks like this:

First we make a decorator that implements the interface and receives our default implementation class in a composite manner.


// decorator to implement the interface
public abstract class PhoneDecorate implements Phone {

    // Get the default implementation class as a combination
    private Phone phone;
    public PhoneDecorate(Phone phone) {
        this.phone = phone;
    }

    @Override
    public void call(a) { phone.call(); }}Copy the code

With decorators, our extensions can be extended based on decorators, just inherit decorators to extend!

We want to listen to music before we call:


// Inherits decorators to extend
public class MusicPhone extends PhoneDecorate {

    public MusicPhone(Phone phone) {
        super(phone);
    }

    // Define the functionality you want to extend
    public void listenMusic(a) {

        System.out.println("Keep running with the pride of a child, how can you see the sparkle of life if you don't stick it out, better to burn than to linger.");

    }

    // Rewrite the call method
    @Override
    public void call(a) {

        // Listen to music before making a phone call
        listenMusic();
        super.call(); }}Copy the code

Now I also want to notify the current time after a phone call, so we extend it by inheriting the decorator class as well:


// This inherits the MusicPhone decorator class
public class GiveCurrentTimePhone extends PhoneDecorate  {


    public GiveCurrentTimePhone(Phone phone) {
        super(phone);
    }

    // Customize the desired function: give the current time
    public void currentTime(a) {
        System.out.println("The current time is:" + System.currentTimeMillis());
    }

    // Override the method to be enhanced
    @Override
    public void call(a) {
        super.call();
        // Notify the current time when you have finished the callcurrentTime(); }}Copy the code

Can complete tasks:

As far as it looks, than I directly inherit the parent class to trouble, and the functional effect is the same…. Let’s move on

At this point, I don’t want to hear the ringtone before I call. It’s simple: we don’t decorate it!

At this point, I want to report the time before I call and listen to the ring back tone after I call.

  • Note: While it is said to change the code in the class,butThis is a reasonable change. Because I defined itGiveCurrentTimePhone classandMusicPhone classIn itself, semanticallyThere’s no ruleOrder of execution of extended functions
  • And inheritance is not the same: first inherit Phone-> implement MusicPhone-> then inherit MusicPhone GiveCurrentTimePhone. This is fixed, the logic of inheritance has already written concrete code, is difficult to change.

So we can still do it very simply:

Second, decoration mode explanation

Maybe some students after reading the above code, or in a daze do not know how to achieve decoration mode “decoration”. Here I will parse it again:

  • Step 1: We have a Phone interface that defines the functions of the Phone
  • Step 2: We have the simplest implementation class, iPhoneX
  • Step 3: Write a decorator abstract class PhoneDecorate that receives our simplest implementation class, iPhoneX, as a composite (constructor pass). In fact, the decorator abstract class acts as a proxy (the core function is still done by the simplest implementation class, iPhoneX, but can be extended to add some functionality that is not present).
  • Step 4: If you want to extend something, inherit the PhoneDecorate abstract class, pass in the objects that you want to enhance (the simplest implementation class, iPhoneX, or objects that have already been enhanced), and complete the extension!

Take a look at the picture below, you will understand!

Often our code can be omitted to look like this.


    // Enhance the function of listening to music first, and then enhance the function of notification time
    Phone phone = new GiveCurrentTimePhone(new MusicPhone(new IphoneX()));
Copy the code

The result is the same:

2.1 Advantages and disadvantages of decoration mode

Advantages:

  • Decorator class and decorator class can be independent, low coupling. Neither needs to know the other exists
  • Decorator mode is an alternative to inheritance, and no matter how many layers are wrapped, the object returned is an IS-A relationship (example above: wrapped or Phone).
  • Implement dynamic extension, as long as inherit the decorator can dynamically extend the desired function.

Disadvantages:

  • Multi-layer decoration is more complex and increases the complexity of the system. Not good for us to debug ~

Third, summary

Finally, the class diagrams for the wrapper and proxy patterns are added:

Objects can be enhanced in three ways:

  • inheritance
  • The packaging mode
  • The proxy pattern

So whenever Java doesn’t give us enough apis, we just need to enhance them. When writing code, a class is written to death and not functional enough, just enhance it!

Understand the packaging pattern and begin your IO journey

References:

  • Zen of Design Patterns
  • Wangjingxin. Top / 2016/10/21 /…

If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat and want to get more Java resources can follow the wechat public account :Java3y.

Article table of Contents navigation:

  • Zhongfucheng.bitcron.com/post/shou-j…