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

How does Java create a model

2025-04-10 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

This article mainly shows you "Java how to create a model", the content is easy to understand, clear, hope to help you solve your doubts, the following let the editor lead you to study and learn "how to create a model in Java" this article.

Create a model

The purpose of a creative schema is to create an object. When it comes to creating an object, the most familiar thing is to new an object, and then set the relevant properties. However, in many scenarios, we need to provide the client with a more friendly way to create objects, especially when we define the class but need to provide it to other developers.

Simple factory model

As simple as the name, very simple, go straight to the code:

Public class FoodFactory {public static Food makeFood (String name) {if (name.equals ("noodle")) {Food noodle = new LanZhouNoodle (); noodle.addSpicy ("more"); return noodle;} else if (name.equals ("chicken")) {Food chicken = new HuangMenChicken (); chicken.addCondiment ("potato"); return chicken } else {return null;}

Where both LanZhouNoodle and HuangMenChicken inherit from Food.

To put it simply, the simple factory pattern is usually like this. A factory class XxxFactory has a static method that returns different instance objects derived from the same parent class (or implementing the same interface) according to our different parameters.

We emphasize the principle of single responsibility, a class provides only one function, and the function of FoodFactory is to be responsible for producing all kinds of Food.

Factory model

The simple factory model is very simple. If it can meet our needs, I don't think we should bother with it. We need to introduce the factory model because we often need to use two or more factories.

Public interface FoodFactory {Food makeFood (String name);} public class ChineseFoodFactory implements FoodFactory {@ Override public Food makeFood (String name) {if (name.equals ("A")) {return new ChineseFoodA ();} else if (name.equals ("B")) {return new ChineseFoodB ();} else {return null }} public class AmericanFoodFactory implements FoodFactory {@ Override public Food makeFood (String name) {if (name.equals ("A")) {return new AmericanFoodA ();} else if (name.equals ("B")) {return new AmericanFoodB ();} else {return null;}

ChineseFoodA, ChineseFoodB, AmericanFoodA and AmericanFoodB are all derived from Food.

The client calls:

Public class APP {public static void main (String [] args) {/ / first select a specific factory FoodFactory factory = new ChineseFoodFactory (); / / the factory in the first step generates specific objects, and different factories create different objects Food food = factory.makeFood ("A");}}

Although makeFood ("A") is used to make Class A food, different factories produce completely different products.

In the first step, we need to select the right factory, and then the second step is basically the same as a simple factory.

The core is that we need to choose the factory we need in the first step. For example, we have a LogFactory interface, and the implementation classes are FileLogFactory and KafkaLogFactory, which correspond to writing logs to a file and to Kafka, respectively. Obviously, our client needs to decide whether to instantiate FileLogFactory or KafkaLogFactory in the first step, which will determine all subsequent operations.

It's simple, but I also draw all the components on one picture so that the reader can see it more clearly:

Rollover failed and re-upload canceled

Abstract factory pattern

When it comes to product families, the abstract factory pattern needs to be introduced.

A classic example is building a computer. Let's not introduce the abstract factory pattern and see how to implement it.

Because the computer is made up of many components, we abstract CPU and motherboard, then CPU is produced by CPUFactory, motherboard is produced by MainBoardFactory, and then we combine CPU and motherboard together, as shown below:

Rollover failed and re-upload canceled

The client call at this time looks like this:

/ / get CPUCPUFactory cpuFactory = new IntelCPUFactory () of Intel; CPU cpu = intelCPUFactory.makeCPU (); / / get motherboard of AMD MainBoardFactory mainBoardFactory = new AmdMainBoardFactory (); MainBoard mainBoard = mainBoardFactory.make (); / / assemble CPU and motherboard Computer computer = new Computer (cpu, mainBoard)

If you look at the CPU factory and the motherboard factory alone, they are the factory model we mentioned earlier. This method is also easy to expand, because to add a hard disk to the computer, you only need to add a HardDiskFactory and the corresponding implementation, and there is no need to modify the existing factory.

However, there is a problem with this approach, that is, if the Intel home-made CPU and AMD motherboards are not compatible, then the code is prone to error, because the client does not know that they are not compatible and will mistakenly be randomly combined.

Here is the concept of a product family, which represents a collection of accessories that make up a product:

When it comes to this product family, the abstract factory pattern is needed to support it. We no longer define CPU factory, motherboard factory, hard disk factory, display factory, etc., we define computer factory directly, each computer factory is responsible for producing all the equipment, which ensures that there are no compatibility problems.

At this time, for the client, it is no longer necessary to select CPU manufacturers, motherboard manufacturers, hard disk manufacturers, etc., directly choose a brand factory, the brand factory will be responsible for the production of all things, and can guarantee that it is compatible and available.

Public static void main (String [] args) {/ / the first step is to select a "big factory" ComputerFactory cf = new AmdFactory (); / / build CPU CPU cpu = cf.makeCPU () from this big factory; / / build motherboard MainBoard board = cf.makeMainBoard () from this big factory; / / build hard disk HardDisk hardDisk = cf.makeHardDisk () from this big factory / / assemble the CPU, motherboard and hard drive from the same factory together Computer result = new Computer (cpu, board, hardDisk);}

Of course, the problem of abstract factories is also obvious. for example, if we want to add a monitor, we need to modify all the factories and add the method of making displays to all factories. This is a bit of a violation of the design principle of closing changes and opening up to extensions.

Singleton mode

The singleton model is used the most and makes the most mistakes.

The hungry model is the simplest:

Public class Singleton {/ / first, block new Singleton () {}; / / create a private static instance, meaning that the first time the class is used, it will create private static Singleton instance = new Singleton (); public static Singleton getInstance () {return instance;} / / blindly write a static method. What I want to say here is that if we just want to call Singleton.getDate (...), / / we do not want to generate a Singleton instance, but there is no way to generate public static Date getDate (String mode) {return new Date ();}}

Many people can talk about the shortcomings of the hungry model, but I think it is rare to encounter this situation in the production process: you define a singleton class and do not need its instance, but you stuff one or more static methods that you will use into this class.

The full mode is the most error-prone:

Public class Singleton {/ / first of all, it is also the first to block the road new Singleton () private Singleton () {} / / compared with the hungry mode, there is no need to instantiate it first. Note the volatile here, which is a necessary private static volatile Singleton instance = null. Public static Singleton getInstance () {if (instance = = null) {/ / locking synchronized (Singleton.class) {/ / this judgment is also necessary, otherwise there will be concurrency problems if (instance = = null) {instance = new Singleton () } return instance;}}

Double check, which refers to checking whether instance is null twice.

Volatile is needed here, hoping to attract the attention of readers.

Many people don't know how to write it, so they just add synchronized to the signature of the getInstance () method, which is too poor.

Nested classes are the most classic, so let's use it in the future:

Public class Singleton3 {private Singleton3 () {} / / mainly uses the feature that nested classes can access static properties and static methods of external classes private static class Holder {private static Singleton3 instance = new Singleton3 ();} public static Singleton3 getInstance () {return Holder.instance;}}

Note that many people will describe this nested class as a static inner class. Strictly speaking, inner classes and nested classes are not the same, and they can access different permissions of external classes.

Finally, someone must jump out and say that enumerations are used to implement singletons, yes, enumerated classes are special, they initialize all instances when the classes are loaded, and JVM ensures that they will not be instantiated again, so it is inherently singleton. Don't say it, the reader is up to it, and it is not recommended to use it.

Builder model

XxxBuilder classes that you often encounter are usually the product of the builder pattern. There are actually many variations of the builder pattern, but for the client, our use is usually the same pattern:

Food food = new FoodBuilder () .a () .b () .c () .build (); Food food = Food.builder () .a () .b () .c () .build ()

The trick is to new a Builder, then call a bunch of methods chained, and finally call the build () method, and we have the objects we need.

Let's have a regular builder model:

Class User {/ / below is a "bunch" of properties private String name; private String password; private String nickName; private int age; / / constructors are privatized, otherwise the client will directly call the constructor private User (String name, String password, String nickName, int age) {this.name = name; this.password = password; this.nickName = nickName; this.age = age } / / static method, which is used to generate a Builder, is not necessary, but it is a good habit to write this method. / / some code requires others to write new User.UserBuilder (). A (). Build () does not look so good public static UserBuilder builder () {return new UserBuilder () } public static class UserBuilder {/ / the following is a bunch of properties exactly the same as User private String name; private String password; private String nickName; private int age; private UserBuilder () {} / / chain call sets each property value and returns this, that is, UserBuilder public UserBuilder name (String name) {this.name = name Return this;} public UserBuilder password (String password) {this.password = password; return this;} public UserBuilder nickName (String nickName) {this.nickName = nickName; return this;} public UserBuilder age (int age) {this.age = age; return this The} / / build () method is responsible for "copying" the properties set in UserBuilder into User. / / of course, you can check public User build () {if (name = = null | | password = = null) {throw new RuntimeException ("user name and password required");} if (age = 150) {throw new RuntimeException ("illegal age") before "copy" } / / you can also do the "default value" function if (nickName = = null) {nickName = name;} return new User (name, password, nickName, age);}

The core is: first set all the properties to Builder, and then copy these properties to the actual generated object when you build () method.

Take a look at the client call:

Public class APP {public static void main (String [] args) {User d = User.builder () .name ("foo") .password ("pAss12345") .age (25) .build ();}

To be honest, the chain writing of the builder pattern is very attractive, but with a lot of "useless" builder code, it feels useless. However, when there are many attributes, some are required, and some are optional, this pattern makes the code much clearer. We can force the caller to provide required fields in the constructor of Builder, and the code is more elegant to validate each parameter in the build () method than in the constructor of User.

Beside the point, readers are strongly advised to use lombok. After using lombok, a lot of code above will look like this:

@ Builderclass User {private String name; private String password; private String nickName; private int age;}

Well, is it possible to do something else with the time saved?

Of course, if you just want chained writing, not builder mode, there is a very simple way: User's getter method remains the same, all setter methods are allowed to return this, and then you can call it like this:

User user = new User () .setName (") .setPassword (") .setAge (20); prototype pattern

This is the last design pattern I'm going to talk about creating a pattern.

The prototype pattern is simple: there is a prototype instance based on which a new instance is generated, that is, "clone".

There is a clone () method in the Object class, which is used to generate a new object. Of course, if we want to call this method, java requires our class to implement the Cloneable interface first. This interface does not define any methods, but if we do not do so, we will throw a CloneNotSupportedException exception when clone ().

Protected native Object clone () throws CloneNotSupportedException

The clone of java is a shallow clone. When an object reference is encountered, the cloned object and the reference in the original object will point to the same object. The usual way to achieve deep cloning is to serialize the object and then deserialize it.

I think it's enough to know about the prototype pattern. It doesn't make sense to say that this code or that code is a prototype pattern in various ways.

The above is all the content of the article "how Java creates a pattern". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

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