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 myself
List<Connection>
To manage. Obviously our object is Connection when writing toclose()
I’m stuck in the method. - Because the function we want is: call
close()
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 call
close()
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 it
GiveCurrentTimePhone class
andMusicPhone class
In 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…