Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Introduction of 9 Design patterns commonly used in Spring

2025-02-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "introduction of 9 design patterns commonly used in Spring". In daily operation, I believe that many people have doubts about the introduction of 9 design patterns commonly used in Spring. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "introduction of 9 design patterns commonly used in Spring". Next, please follow the editor to study!

The first kind: simple factory

Also known as the static factory method (StaticFactory Method) pattern, but it is not one of the 23 GOF design patterns.

The essence of the simple factory pattern is that a factory class dynamically decides which product class should be created based on the parameters passed in.

The BeanFactory in spring is the embodiment of the simple factory pattern. The bean object is obtained by passing in a unique identity, but whether to create it after passing in parameters or before passing in parameters depends on the situation. The configuration is to create an itxxzBean in the HelloItxxz class.

Hello! This is singleton Beanned value > Hello! This is itxxzBean! Value >

Second: factory method (Factory Method)

Usually, the application directly uses new to create new objects. In order to separate the creation and use of the object, the factory mode is adopted, that is, the application hands over the responsibility of object creation and initialization to the factory object.

In general, applications have their own factory objects to create bean. If the application's own factory objects are handed over to Spring management, then Spring manages not the normal bean, but the factory Bean.

The crab takes the static method in the factory method as an example to explain:

Import java.util.Random;public class StaticFactoryBean {public static Integer createRandom () {return new Integer (new Random (). NextInt ());}}

Create a config.xm configuration file and put it into the Spring container to manage. You need to specify the static method name through factory-method.

Test:

Public static void main (String [] args) {/ / returns a random number when calling getBean (). If no factory-method is specified, the instance of StaticFactoryBean will be returned, that is, the instance of factory Bean XmlBeanFactory factory = new XmlBeanFactory (new ClassPathResource ("config.xml")); System.out.println ("I am the instance created by IT learner: + factory.getBean (" random "). ToString ();}

The third kind: singleton mode (Singleton)

Ensure that there is only one instance of a class and provide a global access point to it.

The singleton pattern in spring completes the second half of the sentence, which provides a global access point, BeanFactory. However, the singleton is not controlled at the constructor level, because spring manages arbitrary java objects.

Core cue point: the default bean under Spring is singleton. You can use singleton= "true | false" or scope= "?" To specify

The fourth kind: adapter (Adapter)

In the Aop of Spring, the Advice (notification) is used to enhance the functionality of the proxied class. The principle of Spring to achieve this AOP function is to use the proxy mode (1. JDK dynamic proxy. 2. CGLib bytecode generation technology agent. ) to enhance the aspect of the class at the method level, that is, generate the proxy class of the proxy class, and set the interceptor before the method of the proxy class, enhance the function of the proxy method by executing the heavy content of the interceptor, and realize aspect-oriented programming.

Adapter class interface:

Public interface AdvisorAdapter {boolean supportsAdvice (Advice advice); MethodInterceptor getInterceptor (Advisor advisor);} * * MethodBeforeAdviceAdapter class * *, Adapterclass MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {public boolean supportsAdvice (Advice advice) {return (advice instanceof MethodBeforeAdvice);} public MethodInterceptor getInterceptor (Advisor advisor) {MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice (); return new MethodBeforeAdviceInterceptor (advice);}}

Fifth: wrapper (Decorator)

We encountered such a problem in our project: our project needs to connect to multiple databases, and different customers will access different databases according to their needs in each visit. In the past, we always configured a data source in the spring and hibernate frameworks, so the dataSource property of sessionFactory always points to this data source and is constant, and all DAO access the database through this data source when using sessionFactory.

But now, due to the needs of the project, our DAO has to switch among multiple data sources when accessing sessionFactory, so the problem arises: how to enable sessionFactory to dynamically switch between different data sources according to the needs of customers when performing data persistence? Can we solve it with a few modifications under the framework of spring? Are there any design patterns that can be used?

The first thought is to configure all the dataSource in the applicationContext of spring. These dataSource may be of different types, such as different databases: Oracle, SQL Server, MySQL, etc., or different data sources: such as org.apache.commons.dbcp.BasicDataSource provided by apache, org.springframework.jndi.JndiObjectFactoryBean provided by spring, and so on. Then sessionFactory sets the dataSource property to a different data source according to each request of the customer to achieve the purpose of switching the data source.

The wrapper pattern used in spring has two representations on class names: one is that the class name contains Wrapper, and the other is that the class name contains Decorator. Basically, you add some additional responsibilities to an object dynamically.

Sixth: agent (Proxy)

Provide a proxy for other objects to control access to this object. It is structurally similar to the Decorator pattern, but Proxy is a control, more like a limitation of functionality, while Decorator is an added responsibility.

Spring's Proxy pattern is reflected in aop, such as JdkDynamicAopProxy and Cglib2AopProxy.

Seventh: observer (Observer)

Define an one-to-many dependency between objects. When the state of an object changes, all objects that depend on it are notified and updated automatically.

The common place of Observer pattern in spring is the implementation of listener. Such as ApplicationListener.

Type 8: strategy (Strategy)

Define a series of algorithms, encapsulate them one by one, and make them interchangeable. This mode allows the algorithm to change independently of the customers who use it.

Strategy schema is used in spring when instantiating objects.

The following code in SimpleInstantiationStrategy illustrates the use of policy mode:

Ninth: template method (Template Method)

Define the skeleton of an algorithm in an operation and defer some steps to a subclass. Template Method enables subclasses to redefine certain steps of an algorithm without changing the structure of the algorithm.

Template Method schemas generally need to be inherited. Here I want to explore another understanding of Template Method.

JdbcTemplate in spring does not want to inherit this class when using this class, because there are too many methods in this class, but we still want to use the stable, public database connections that JdbcTemplate already has, so what do we do? We can extract the changes and pass them into the JdbcTemplate method as a parameter. But the change is a piece of code, and this code uses variables in JdbcTemplate.

What shall I do? Then let's use the callback object. Define a method to manipulate variables in JdbcTemplate in this callback object, and let's implement this method and focus on the changes here. Then we pass the callback object to JdbcTemplate, which completes the call. This may be another implementation that Template Method does not need to inherit.

This series of articles will be sorted out in my Java interview Guide warehouse on GitHub. Please check out more wonderful content in my warehouse.

Https://github.com/h3pl/Java-Tutorial

If you like, please trouble Star and fork.

The article will also be published on my personal blog, the reading experience is better:

Www.how2playlife.com

Structural model

The previous creation pattern introduced some of the design patterns for creating objects. The structural patterns introduced in this section are designed to decouple our code by changing the structure of the code, making our code easy to maintain and extend.

Agent mode

The first proxy pattern to be introduced is one of the most commonly used patterns, using a proxy to hide the implementation details of a specific implementation class, and usually to add some logic before and after the real implementation.

Since it is an agent, it is necessary to hide the real implementation from the client, and the agent is responsible for all requests from the client. Of course, the agent is just an agent, it will not complete the actual business logic, but a layer of skin, but for the client, it must appear to be the real implementation that the client needs.

To understand the word agent, this model is actually simple.

Public interface FoodService {Food makeChicken (); Food makeNoodle ();} public class FoodServiceImpl implements FoodService {public Food makeChicken () {Food f = new Chicken () f.setChicken ("1kg"); f.setSpicy ("1g"); f.setSalt ("3G"); return f;} public Food makeNoodle () {Food f = new Noodle (); f.setNoodle ("500g") F.setSalt ("5g"); return f;}} / / proxy wants to behave like a real implementation class, so you need to implement a real implementation class inside FoodServicepublic class FoodServiceProxy implements FoodService {/ /. Of course, you can also inject private FoodService foodService = new FoodServiceImpl () through the constructor. Public Food makeChicken () {System.out.println ("We're going to start making chicken soon"); / / if we define this as the core code, then the core code is done by the real implementation class, / / the agent just does something "insignificant" before and after the core code Food food = foodService.makeChicken () System.out.println ("chicken is finished, add some pepper"); / / enhanced food.addCondiment ("pepper"); return food;} public Food makeNoodle () {System.out.println ("ready to make ramen ~"); Food food = foodService.makeNoodle (); System.out.println ("finished") return food;}}

Client call, note that we are going to instantiate the interface with a proxy:

/ / use the proxy class to instantiate FoodService foodService = new FoodServiceProxy (); foodService.makeChicken ()

We found that no, the agent model is to do "method packaging" or "method enhancement". In aspect-oriented programming, forget it and don't flatter the noun. In AOP, it is actually the process of dynamic proxy. For example, in Spring, we don't define the proxy class ourselves, but Spring will help us define the proxy dynamically, and then dynamically add the code logic we defined in @ Before, @ After, @ Around to the proxy.

When it comes to dynamic agents, we can expand and say... There are two kinds of dynamic proxy in Spring, one is that if our class defines interfaces, such as UserService interface and UserServiceImpl implementation, then use JDK dynamic proxy, interested readers can look at the source code of java.lang.reflect.Proxy class; the other is that we do not have a defined interface, Spring will use CGLIB for dynamic proxy, it is a jar package, the performance is good.

Adapter mode

After talking about the proxy pattern, we say the adapter pattern because they are very similar, so we can make a comparison here.

What the adapter pattern does is that there is an interface that needs to be implemented, but our ready-made objects are not satisfied, and we need to add a layer of adapters to adapt.

Generally speaking, there are three kinds of adapter patterns: default adapter pattern, object adapter pattern, and class adapter pattern. Don't be in a hurry to distinguish these, let's look at the examples.

Default adapter mode

First, let's look at what the simplest adapter pattern, the default adapter pattern (Default Adapter), looks like.

We use FileAlterationListener in the Appache commons-io package as an example. This API defines many methods for monitoring files or folders. Once the corresponding action occurs, the corresponding method will be triggered.

Public interface FileAlterationListener {void onStart (final FileAlterationObserver observer); void onDirectoryCreate (final File directory); void onDirectoryChange (final File directory); void onDirectoryDelete (final File directory); void onFileCreate (final File file); void onFileChange (final File file); void onFileDelete (final File file); void onStop (final FileAlterationObserver observer);}

A big problem with this interface is that there are too many abstract methods, and if we're going to use this interface, it means we have to implement every abstract method, and if we just want to monitor file creation and file deletion events in the folder, but we still have to implement all the methods, which is obviously not what we want.

So, we need the following adapter to implement the above interface, but all the methods are empty methods, so we can define our own class instead to inherit the following class.

Public class FileAlterationListenerAdaptor implements FileAlterationListener {public void onStart (final FileAlterationObserver observer) {} public void onDirectoryCreate (final File directory) {} public void onDirectoryChange (final File directory) {} public void onDirectoryDelete (final File directory) {} public void onFileCreate (final File file) {} public void onFileChange (final File file) {} public void onFileDelete (final File file) {} public void onStop (final FileAlterationObserver observer) {}}

For example, we can define the following classes, and we just need to implement the methods we want to implement:

Public class FileMonitor extends FileAlterationListenerAdaptor {public void onFileCreate (final File file) {/ / File creation doSomething ();} public void onFileDelete (final File file) {/ / File deletion doSomething ();}}

Of course, the above is only one of the adapter patterns, and it is also the simplest, needless to say. Next, we will introduce the "orthodox" adapter pattern.

Object adapter pattern

Let's take a look at an example of the "Head First design pattern". I modified it a little bit to see how to fit a chicken into a duck so that it can also be used as a duck. Because, right now, we don't have a suitable implementation class for the duck interface, so we need an adapter.

Public interface Duck {public void quack (); / / duck quack public void fly (); / Flying} public interface Cock {public void gobble (); / / Chicken cooing public void fly (); / / Flying} public class WildCock implements Cock {public void gobble () {System.out.println ("cooing") } public void fly () {System.out.println ("chickens can fly");}}

Duck interface has fly () and quare () two methods, chicken Cock if you want to impersonate a duck, fly () method is ready-made, but the chicken can not duck quack, there is no quack () method. This is the time to adapt:

/ / there is no doubt that first of all, this adapter must need implements Duck, so that it can be used as a duck to use an instance of a chicken in the public class CockAdapter implements Duck {Cock cock; / / construction method, which is to adapt the chicken to a duck to use public CockAdapter (Cock cock) {this.cock = cock. } / / realize the duck quack method @ Override public void quack () {/ / inside is actually a chicken cooing cock.gobble ();} @ Override public void fly () {cock.fly ();}}

The client call is simple:

Public static void main (String [] args) {/ / there is a pheasant Cock wildCock = new WildCock (); / / the pheasant is successfully adapted into a duck Duck duck = new CockAdapter (wildCock);.}

At this point, everyone knows what the adapter pattern is all about. It's just that we need a duck, but we only have a chicken, so we need to define an adapter to act as a duck, but the methods in the adapter are implemented by the chicken.

Let's use a diagram to illustrate briefly:

The above picture should be easy to understand, so I won't explain it any more. Next, let's see what the class adaptation model looks like.

Class adapter pattern

Cut the crap and go straight to the picture:

Seeing this diagram, it should be easy for you to understand that through inheritance, the adapter automatically obtains most of the methods needed. At this point, it is easier for the client to use, just Target t = new SomeAdapter ();.

Adapter pattern summary

Similarities and differences between class adaptation and object adaptation

One adopts inheritance, the other adopts combination.

Class adaptation belongs to static implementation, object adaptation belongs to the dynamic implementation of composition, and object adaptation requires multiple instantiation of an object.

In general, object adaptation is used more often.

Similarities and differences between Adapter pattern and Agent pattern

Comparing these two patterns is actually a comparison between the object adapter pattern and the proxy pattern, which are very similar in code structure and require a specific instance of the implementation class. But their purpose is different, the proxy pattern does the work of enhancing the original method, and the adapter does the adaptive work in order to provide "packaging the chicken into a duck and then using it as a duck". There is no inheritance relationship between the chicken and the duck.

Bridge mode

To understand the bridge pattern is to understand code abstraction and decoupling.

First of all, we need a bridge, which is an interface that defines the interface methods provided.

Public interface DrawAPI {public void draw (int radius, int x, int y);}

Then there is a series of implementation classes:

Public class RedPen implements DrawAPI {@ Override public void draw (int radius, int x, int y) {System.out.println ("draw with a red pen, radius:" + radius + ", x:" + x + ", y:" + y) }} public class GreenPen implements DrawAPI {@ Override public void draw (int radius, int x, int y) {System.out.println ("draw with a green pen, radius:" + radius + ", x:" + x + ", y:" + y) }} public class BluePen implements DrawAPI {@ Override public void draw (int radius, int x, int y) {System.out.println ("draw with a blue pen, radius:" + radius + ", x:" + x + ", y:" + y);}}

Define an abstract class whose implementation classes need to use DrawAPI:

Public abstract class Shape {protected DrawAPI drawAPI; protected Shape (DrawAPI drawAPI) {this.drawAPI = drawAPI;} public abstract void draw ();}

Define subclasses of an abstract class:

/ / Circular public class Circle extends Shape {private int radius; public Circle (int radius, DrawAPI drawAPI) {super (drawAPI); this.radius = radius;} public void draw () {drawAPI.draw (radius, 0,0);}} / / rectangular public class Rectangle extends Shape {private int x; private int y; public Rectangle (int x, int y, DrawAPI drawAPI) {super (drawAPI) This.x = x; this.y = y;} public void draw () {drawAPI.draw (0, x, y);}}

Finally, let's take a look at the client side demonstration:

Public static void main (String [] args) {Shape greenCircle = new Circle (10, new GreenPen ()); Shape redRectangle = new Rectangle (4,8, new RedPen ()); greenCircle.draw (); redRectangle.draw ();}

Maybe it's not very clear when you see the above step by step. I put everything into one picture:

This time you should know where the abstraction is and how to decouple it. The advantage of the bridge model is also obvious, that is, it is very easy to expand.

This section refers to the example here and modifies it.

Decoration mode

It is not easy to explain the pattern of decoration clearly. Perhaps the reader knows that several classes in Java IO are typical decorative pattern applications, but the reader may not be clear about the relationship, and may forget it after reading it. I hope that after reading this section, the reader will have a deeper understanding of it.

First of all, let's look at a simple diagram, and when we look at this diagram, we can understand the hierarchical structure:

Let's talk about the starting point of the decoration pattern. We can see from the figure that the interface Component already has two implementation classes, ConcreteComponentA and ConcreteComponentB. However, if we want to enhance these two implementation classes, we can use the decoration pattern and decorate the implementation class with specific decorators to achieve the purpose of enhancement.

Explain the decorator in terms of the name. Since it is said to be decoration, then it is often to add small functions like this, and we want to meet the need to add multiple small functions. In the simplest way, the proxy pattern can enhance the functionality, but it is not easy for the agent to enhance multiple functions. Of course, you can say that you can wrap the agent with the agent, but then the code is complicated.

First of all, understand some simple concepts, from the figure, we can see that all the specific decorators ConcreteDecorator can be used as Component, because they all implement all the interfaces in Component. The difference between them and the Component implementation class ConcreteComponent is that they are just decorators, that is, even though they look awesome, they are just decorated with a layer of skin in the concrete implementation.

Pay attention to the Component and Decorator mixed in the nouns in this passage. Don't get confused.

Let's take a look at an example, first figure out the decoration pattern, and then introduce the application of the decoration pattern in java io.

Recently, "Happy Lemon" has become popular in the street. We divide happy lemon drinks into three categories: black tea, green tea and coffee. On the basis of these three categories, many flavors have been added, such as kumquat lemon black tea, kumquat lemon pearl green tea, mango black tea, mango green tea, mango pearl black tea, roasted pearl black tea, roasted pearl mango green tea, coconut germ coffee, caramel cocoa coffee and so on. Every store has a long menu, but if you take a closer look, you can see that there are not many kinds of ingredients, but there are a lot of combinations, and if customers need them, they can also make a lot of drinks that don't appear on the menu.

In this example, black tea, green tea and coffee are the most basic drinks, while others such as kumquat, lemon, mango, pearl, coconut and caramel are decorative. Of course, in development, we can really develop these classes like stores: LemonBlackTea, LemonGreenTea, MangoBlackTea, MangoLemonGreenTea. However, we soon found that this kind of Zigan must not work, which will cause us to combine all the possibilities, and what if the guest needs to add double lemons to the black tea? What about three lemons? In case a pervert asks for four lemons, it's for yourself to work overtime.

Cut the crap and put on the code.

First, define the beverage abstract base class:

Public abstract class Beverage {/ / return description public abstract String getDescription (); / / return price public abstract double cost ();}

Then there are three basic beverage implementation classes, black tea, green tea and coffee:

Public class BlackTea extends Beverage {public String getDescription () {return "black tea";} public double cost () {return 10;}} public class GreenTea extends Beverage {public String getDescription () {return "green tea";} public double cost () {return 11;}}. / / Coffee omitted

Define the seasoning, which is the decorator's base class, which must inherit from Beverage:

/ / seasoning public abstract class Condiment extends Beverage {}

Then let's define specific seasonings such as lemon and mango, which belong to the decorator, and there is no doubt that these seasonings must inherit the Condiment class:

Public class Lemon extends Condiment {private Beverage bevarage; / / here is very critical, you need to import specific drinks, such as black tea or green tea that is not decorated, / / of course, you can also import mango green tea that has been decorated, so that you can make mango lemon green tea public Lemon (Beverage bevarage) {this.bevarage = bevarage. } public String getDescription () {/ / decorative return bevarage.getDescription () + ", add lemon";} public double cost () {/ / decorative return beverage.cost () + 2; / / add lemon for 2 yuan}} public class Mango extends Condiment {private Beverage bevarage; public Mango (Beverage bevarage) {this.bevarage = bevarage } public String getDescription () {return bevarage.getDescription () + ", add mango";} public double cost () {return beverage.cost () + 3; / / add 3 yuan to mango}}. / / add a class to each seasoning

Look at the client call:

Public static void main (String [] args) {/ / first, we need a basic drink, black tea, green tea or coffee Beverage beverage = new GreenTea (); / / start decorating beverage = new Lemon (beverage); / / add a lemon beverage = new Mongo (beverage); / / add a mango System.out.println (beverage.getDescription () + "Price: ¥" + beverage.cost ()) / / "Green tea, lemon and mango price: ¥16"}

If we need mango pearl double lemon black tea:

Beverage beverage = new Mongo (new Pearl (new Lemon (new Lemon (new BlackTea ())

Isn't that sick?

If you look at the following picture, it may be clearer:

By now, everyone should be clear about the decoration mode.

Next, let's talk about the decoration patterns in java IO. Take a look at the following figure, some of the classes derived from InputStream:

We know that InputStream represents the input stream, and the specific input sources can be FileInputStream, PipedInputStream, ByteArrayInputStream, and so on, just like black tea and green tea in the previous example of milk tea, which belong to the basic input stream.

FilterInputStream inherits the key nodes of the decoration mode, and its implementation class is a series of decorators, such as BufferedInputStream represents to be decorated with buffers, which makes the input stream have the function of buffering, LineNumberInputStream represents decorated with line numbers, which can be obtained during operation, DataInputStream decoration, so that we can convert from the input stream to the basic type values in java.

Of course, in java IO, if we use decorators, it is not very suitable for interface-oriented programming, such as:

InputStream inputStream = new LineNumberInputStream (new BufferedInputStream (new FileInputStream (")

As a result, InputStream still does not have the ability to read line numbers, because the method to read line numbers is defined in the LineNumberInputStream class.

We should use it like this:

DataInputStream is = new DataInputStream (new BufferedInputStream (new FileInputStream (")

So it's hard to find pure code that strictly conforms to the design pattern.

Facade mode

Facade mode (also known as appearance mode, Facade Pattern) is used in many source code, such as slf4j can be understood as the application of facade mode. This is a simple design pattern. Let's go straight to the code and talk about it.

First, we define an interface:

Public interface Shape {void draw ();}

Define several implementation classes:

Public class Circle implements Shape {@ Override public void draw () {System.out.println ("Circle::draw ()");}} public class Rectangle implements Shape {@ Override public void draw () {System.out.println ("Rectangle::draw ()");}}

The client calls:

Public static void main (String [] args) {/ / draw a circle Shape circle = new Circle (); circle.draw (); / / draw a rectangle Shape rectangle = new Rectangle (); rectangle.draw ();}

The above is the code we often write. If we need to draw a circle, we need to instantiate the circle, and to draw a rectangle, we need to instantiate a rectangle, and then call the corresponding draw () method.

Next, let's take a look at how to use facade mode to make client calls more friendly.

Let's first define a facade:

Public class ShapeMaker {private Shape circle; private Shape rectangle; private Shape square; public ShapeMaker () {circle = new Circle (); rectangle = new Rectangle (); square = new Square ();} / * define a bunch of methods, which should be called, and this facade determines * / public void drawCircle () {circle.draw () } public void drawRectangle () {rectangle.draw ();} public void drawSquare () {square.draw ();}}

Take a look at how the client calls:

Public static void main (String [] args) {ShapeMaker shapeMaker = new ShapeMaker (); / / client calls are now clearer: shapeMaker.drawCircle (); shapeMaker.drawRectangle (); shapeMaker.drawSquare ();}

The advantage of the facade pattern is obvious. Instead of focusing on which implementation class should be used for instantiation, the client can just call the method provided by the facade, because the method name provided by the facade class is already friendly to the client.

Combination mode

The composition pattern is used to represent hierarchical data, which makes our access to individual objects and composite objects consistent.

Looking directly at an example, each employee has attributes such as name, department and salary, as well as a collection of subordinate employees (although the set may be empty), and subordinate employees have the same structure as their own, with attributes such as name and department. At the same time, there is also a collection of subordinates.

Public class Employee {private String name; private String dept; private int salary; private List subordinates; / / subordinate public Employee (String name,String dept, int sal) {this.name = name; this.dept = dept; this.salary = sal; subordinates = new ArrayList ();} public void add (Employee e) {subordinates.add (e);} public void remove (Employee e) {subordinates.remove (e) } public List getSubordinates () {return subordinates;} public String toString () {return ("Employee: [Name:" + name + ", dept:" + dept + ", salary:" + salary+ "]");}}

Typically, this class needs to define methods such as add (node), remove (node), and getChildren ().

In fact, this is the combination mode, this simple model I will not introduce too much, I believe that readers do not like to see me write nonsense.

Sharing meta-mode

English is Flyweight Pattern. I don't know who translated the word first. I feel that the translation is really difficult to understand. Let's try to force the connection. Flyweight means lightweight, and sharing elements separately means sharing components, that is, reusing generated objects, which is, of course, lightweight.

The easiest way to reuse objects is to use a HashMap to store each newly generated object. Every time you need an object, go to the HashMap to see if there is one, if not, generate a new object, and then put the object into the HashMap.

I won't demonstrate this simple code.

At this point, the study of "introduction to 9 design patterns commonly used in Spring" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report