In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
Design pattern (Design pattern) is a set of repeatedly used, well-known, classified and cataloged summary of code design experience. Design patterns are used to reuse code, make it easier for others to understand, and ensure code reliability. There is no doubt that design patterns are win-win for others and systems. Design patterns make the code really engineering. Design patterns are the cornerstone of software engineering, just like the bricks and stones of a building. The reasonable use of design patterns in the project can perfectly solve many problems, and each pattern now has corresponding principles to correspond to it. Each pattern describes a problem that occurs repeatedly around us, as well as the core solution to the problem, which is why it can be widely used.
I. Classification of design patterns
In general, design patterns fall into three categories:
There are five creative models: factory method pattern, abstract factory pattern, singleton pattern, builder pattern, prototype pattern.
There are seven structural patterns: adapter mode, decorator mode, proxy mode, appearance mode, bridge mode, combination mode, sharing meta-mode.
There are eleven behavioral patterns: strategy model, template method model, observer model, iterative sub-model, chain of responsibility model, command mode, memo mode, state mode, visitor mode, intermediary mode, interpreter mode.
In fact, there are two types: concurrency mode and thread pool mode. Describe it as a whole with a picture:
II. Design patterns in Java 23
From this part, we introduce in detail the concepts and application scenarios of 23 design patterns in Java, and analyze them combined with their characteristics and the principles of design patterns.
1. Factory method Model (Factory Method)
There are three factory method models:
11. The common factory pattern is to create a factory class to create instances of some classes that implement the same interface. First, take a look at the diagram:
Examples are as follows: (let's give an example of sending emails and text messages)
First, create a common interface between the two:
Public interface Sender {
Public void Send ()
}
Second, create an implementation class:
Public class MailSender implements Sender {
@ Override
Public void Send () {
System.out.println ("this is mailsender!")
}
}
Public class SmsSender implements Sender {
@ Override
Public void Send () {
System.out.println ("this is sms sender!")
}
}
Finally, build the factory class:
Public class SendFactory {
Public Sender produce (String type) {
If ("mail" .equals (type)) {
Return new MailSender ()
} else if ("sms" .equals (type)) {
Return new SmsSender ()
} else {
System.out.println ("please enter the correct type!")
Return null
}
}
}
Let's test it:
Public class FactoryTest {
Public static void main (String [] args) {
SendFactory factory = new SendFactory ()
Sender sender = factory.produce ("sms")
Sender.Send ()
}
}
Output: this is sms sender!
22. Multiple factory method patterns are improvements to ordinary factory method patterns. In ordinary factory method patterns, objects cannot be created correctly if the passed string is wrong, while multiple factory method patterns provide multiple factory methods to create objects separately. Diagram:
:: _ _ IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::2
Just make changes to the above code and change the SendFactory class, as follows:
Public class SendFactory {
Public Sender produceMail () {
Return new MailSender ()
}
Public Sender produceSms () {
Return new SmsSender ()
}
}
The test classes are as follows:
Public class FactoryTest {
Public static void main (String [] args) {
SendFactory factory = new SendFactory ()
Sender sender = factory.produceMail ()
Sender.Send ()
}
}
Output: this is mailsender!
33. Static factory method mode. Set the methods in the above factory method patterns to static. You don't need to create an instance, and you can call them directly.
Public class SendFactory {
Public static Sender produceMail () {
Return new MailSender ()
}
Public static Sender produceSms () {
Return new SmsSender ()
}
}
Public class FactoryTest {
Public static void main (String [] args) {
Sender sender = SendFactory.produceMail ()
Sender.Send ()
}
}
Output: this is mailsender!
In general, the factory pattern is suitable: whenever there are a large number of products that need to be created and have a common interface, they can be created through the factory method pattern. In the above three modes, the first cannot create the object correctly if the string is incorrect, and the third does not need to instantiate the factory class relative to the second, so, in most cases, we will choose the third-static factory method mode.
2. Abstract factory pattern (Abstract Factory)
One problem with the factory method pattern is that the creation of the class depends on the factory class, that is, if you want to expand the program, you must modify the factory class, which violates the closure principle, so, from a design point of view, there are certain problems. How to solve it? Use the abstract factory pattern to create multiple factory classes, so that if you need to add new functionality, you can just add a new factory class without modifying the previous code. Because abstract factories are not easy to understand, let's first look at the diagram, and then with the code, it is easier to understand.
Take a look at the example:
Public interface Sender {
Public void Send ()
}
Two implementation classes:
Public class MailSender implements Sender {
@ Override
Public void Send () {
System.out.println ("this is mailsender!")
}
}
Public class SmsSender implements Sender {
@ Override
Public void Send () {
System.out.println ("this is sms sender!")
}
}
Two factory classes:
Public class SendMailFactory implements Provider {
@ Override
Public Sender produce () {
Return new MailSender ()
}
}
Public class SendSmsFactory implements Provider {
@ Override
Public Sender produce () {
Return new SmsSender ()
}
}
In providing an interface:
Public interface Provider {
Public Sender produce ()
}
Test class:
Public class Test {
Public static void main (String [] args) {
Provider provider = new SendMailFactory ()
Sender sender = provider.produce ()
Sender.Send ()
}
}
In fact, the advantage of this model is that if you want to add a function: send timely messages, you only need to do an implementation class, implement the Sender interface, and do a factory class to implement the Provider interface, and then OK, without having to change the ready-made code. In this way, the expansibility is better!
3. Singleton mode (Singleton)
Singleton object (Singleton) is a common design pattern. In Java applications, singleton objects can guarantee that only one instance of the object exists in a JVM. This model has several benefits:
1. Some classes are created frequently, which is a lot of system overhead for some large objects.
2. Omit the new operator, reduce the use frequency of the system memory, and reduce the pressure of GC.
3. Some classes, such as the core trading engine of the exchange, control the trading process, and if more than one can be created, the system is completely messed up. (for example, if there are multiple commanders in an army at the same time, there will be chaos), so only by using singleton mode can we ensure that the core transaction server independently controls the whole process.
First, let's write a simple singleton class:
Public class Singleton {
/ * hold a private static instance to prevent it from being referenced. Here, it is assigned as null to achieve delayed loading * /
Private static Singleton instance = null
/ * Private constructors to prevent instantiation * /
Private Singleton () {
}
/ * static engineering method, create an instance * /
Public static Singleton getInstance () {
If (instance = = null) {
Instance = new Singleton ()
}
Return instance
}
/ * if the object is used for serialization, you can ensure that the object is consistent before and after serialization * /
Public Object readResolve () {
Return instance
}
}
This class can meet the basic requirements, but for a class like this without thread safety protection, if we put it in a multithreaded environment, there will certainly be a problem, how to solve it? We will first think of adding the synchronized keyword to the getInstance method, as follows:
Public static synchronized Singleton getInstance () {
If (instance = = null) {
Instance = new Singleton ()
}
Return instance
}
However, the synchronized keyword locks this object, and this usage degrades performance, because every time you call getInstance (), you lock the object. In fact, you only need to lock it when you create the object for the first time, and then you don't need it, so this area needs to be improved. Let's change it to the following:
Public static Singleton getInstance () {
If (instance = = null) {
Synchronized (instance) {
If (instance = = null) {
Instance = new Singleton ()
}
}
}
Return instance
}
It seems to solve the problem mentioned earlier, adding the synchronized keyword internally, that is, it does not need to be locked when it is called, but only when the instance is null and the object is created, and the performance is improved to a certain extent. However, in such a case, there can still be problems, as shown in the following situation: the creation of objects and assignments in the Java instruction are done separately, that is, instance = new Singleton (); the statement is executed in two steps. However, JVM does not guarantee the order of these two operations, which means that it is possible that JVM will allocate space to the new Singleton instance, then assign values directly to instance members, and then initialize the Singleton instance. This may go wrong, let's take An and B threads as an example:
A > An and B threads enter the first if judgment at the same time
B > A first enters the synchronized block. Since instance is null, it executes instance = new Singleton ()
C > due to the optimization mechanism within JVM, JVM first draws some blank memory allocated to the Singleton instance and assigns values to the instance members (note that JVM does not start initializing the instance at this time), and then A leaves the synchronized block. Design patterns in the classic framework JAVA 23 design patterns introduction to proficiency in the classic framework design patterns JAVA 23 design patterns proficiency in the classic framework JAVA 23 design patterns proficiency in the classic framework JAVA 23 design patterns proficiency in the classic framework design patterns JAVA 23 design patterns introduction to proficiency
D > B enters the synchronized block, and since instance is not a null at this time, it immediately leaves the synchronized block and returns the result to the program that called the method.
E > at this point, the B thread intends to use the Singleton instance, only to find that it has not been initialized, and an error occurs.
So the program may still have errors, in fact, the process of running the program is very complex, from which we can see that it is more difficult and challenging to write programs in a multi-threaded environment. We further optimize the program:
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.