-
public class Person {
-
private String name;
-
private String password;
-
private String birthday;
-
private int age;
-
-
public void setName(String name) {
-
this.name = name.toUpperCase();
-
}
-
-
public String getName() {
-
return this.name;
-
}
-
-
public void setPassword(String password) {
-
this.password = password;
-
}
-
-
public String getPassword() {
-
return this.password;
-
}
-
-
public void setBirthday(String birthday) {
-
this.birthday = birthday;
-
}
-
-
public String getBirthday() {
-
return this.birthday;
-
}
-
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
public int getAge() {
-
return this.age;
-
}
-
-
}
In most cases, the combination of set and get methods is sufficient. Sometimes, however, there are other actions in this class. For example, the Person class also defines the login action. The login action verifies the user's username and password. If the user's name and password are entered correctly, the login will be successful. But the actual business is often not so simple. For example, the user may enter a short message authentication code during login. Then, when waiting for the short message of authentication code, the user password changes for some reason (for example, setPassword method is called elsewhere), which causes the password verification to pass before receiving authentication code, but fails after entering authentication code.
Builder pattern
For this reason, the builder model emerges as the times require. It separates the representation and construction of objects, that is to say, the use of objects is divided into two steps: the first step is to input various parameters to construct, at this time only setting attributes can not operate business actions; the second step is to carry out business actions according to the constructed objects, and at this time can not modify property settings. Just like the construction company repairing bridges and roads, the amount of cement, sand and reinforcement is determined according to the design scheme, and then the construction materials are processed step by step. If someone reduces the amount of cement or replaces steel bars with cement in the process of construction, the project will mostly become tofu dregs project.
The builder pattern is specific to code implementation. It uses the form of internal classes to separate the building parts. See the description of internal classes.<
Android Development Notes (86) Several Special Classes " That is to say, an internal class Builder is defined in the Person class, and the Builder class completes the parameter setting and other construction operations. In addition, in order to ensure that each attribute value of an object is assigned in order only, final modifiers can be added to each attribute. See the introduction of final.<
Android Development Notes (87) Several Modified Keywords " Following is a code example of transforming the Person class into the builder pattern:
-
public class Person {
-
private final String name;
-
private final String password;
-
private final String birthday;
-
private final int age;
-
-
public String getName() {
-
return this.name;
-
}
-
-
public String getPassword() {
-
return this.password;
-
}
-
-
public String getBirthday() {
-
return this.birthday;
-
}
-
-
public int getAge() {
-
return this.age;
-
}
-
-
public void login() {
-
-
}
-
-
private Person(Builder builder) {
-
this.name = builder.name;
-
this.password = builder.password;
-
this.birthday = builder.birthday;
-
this.age = builder.age;
-
}
-
-
public static class Builder {
-
private String name;
-
private String password;
-
private String birthday;
-
private int age;
-
-
public Builder setName(String name) {
-
this.name = name.toUpperCase();
-
return this;
-
}
-
-
public Builder setPassword(String password) {
-
this.password = password;
-
return this;
-
}
-
-
public Builder setBirthday(String birthday) {
-
this.birthday = birthday;
-
return this;
-
}
-
-
public Builder setAge(int age) {
-
this.age = age;
-
return this;
-
}
-
-
public Person build() {
-
return new Person(this);
-
}
-
-
}
-
-
}
Primary usage
As we know, there are several ways to construct strings in java:
1. Several strings are connected by "+".
2. Call String.format method for string formatting;
3. StringBuilder class is used to construct strings.
The third is the primary model of the builder model. By calling append, insert, delete of StringBuilder class to modify the content, and finally calling toString method to output the constructed string.
Of course, StringBuilder is a separate class, not an internal class of String class, and it is not an operation of specific attributes, so StringBuilder is not a real builder pattern. Similar to StringBuilder, but also using the builder model, this example is Uri.Builder. However, the construction process has been encapsulated in Uri, and the use of Builder is not open to the outside world. Usually we can get Uri instances by calling Uri.parse or Uri.withAppendedPath methods.
Looking at the source code of the withAppendedPath method, you can see that it is built internally with Builder:
-
public static Uri withAppendedPath(Uri baseUri, String pathSegment) {
-
Builder builder = baseUri.buildUpon();
-
builder = builder.appendEncodedPath(pathSegment);
-
return builder.build();
-
}
BuilUpon is an abstract method that needs to be rewritten in concrete classes. Following is the rebuilt buildUpon method of StringUri class. You can see the construction process of the detailed parameters.
-
public Builder buildUpon() {
-
if (isHierarchical()) {
-
return new Builder()
-
.scheme(getScheme())
-
.authority(getAuthorityPart())
-
.path(getPathPart())
-
.query(getQueryPart())
-
.fragment(getFragmentPart());
-
} else {
-
return new Builder()
-
.scheme(getScheme())
-
.opaquePart(getSsp())
-
.fragment(getFragmentPart());
-
}
-
}
Use occasions in Android
In Android, builder mode is used, which is usually related to asynchronous operation. Because the waiting time of asynchronous operation is long, it is very likely that the attribute values will change during the waiting process. In order to avoid the exception caused by the attribute changes, the builder mode should be introduced. Common application scenarios for builder mode include dialog box Alert Dialog, notification push Notification, collection animation Animator Set, and image caching framework.
AlertDialog
For a detailed introduction to Alert Dialog, see<
Android Development Notes (66) Custom Dialog Box " Below is an example of AlertDialog.Builder's usage code:
-
AlertDialog.Builder builder = new AlertDialog.Builder(this);
-
builder.setTitle("It's a lovely day today.");
-
builder.setMessage("Where shall we play?");
-
builder.setPositiveButton("Sure?", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
showToast("Yeah, let's go for a big meal.");
-
}
-
});
-
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
showToast("Unfortunately, I've already made an appointment with someone else.");
-
}
-
});
-
builder.setNeutralButton("neutral", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface dialog, int which) {
-
showToast("Well, I have something to do today. Is tomorrow OK?");
-
}
-
});
-
AlertDialog alert = builder.create();
-
alert.show();
Notification
For a detailed introduction to Notification, see<
Android Development Notes (52) Notification Notification " Here is an example of Notification.Builder's usage code:
-
Notification.Builder builder = new Notification.Builder(this);
-
builder.setContentIntent(contentIntent)
-
.setDeleteIntent(deleteIntent)
-
.setUsesChronometer(true)
-
.setProgress(100, 60, false)
-
.setSubText("Here is a copy.")
-
.setNumber(99)
-
.setAutoCancel(false)
-
.setSmallIcon(R.drawable.tt_s)
-
.setTicker("Prompt text")
-
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.tt_s))
-
.setContentTitle("Title Text")
-
.setContentText("Content text");
-
Notification notify = builder.build();
-
-
NotificationManager notifyMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-
notifyMgr.notify(R.string.app_name, notify);
AnimatorSet
Detailed introduction to AnimatorSet<
Android Development Notes (96) Collection Animation and Attribute Animation " Here is an example of the usage code of AnimatorSet.Builder:
-
ObjectAnimator anim1 = ObjectAnimator.ofFloat(tv_text, "alpha", 1f, 0.1f, 1f, 0.5f, 1f);
-
ObjectAnimator anim2 = ObjectAnimator.ofFloat(tv_text, "rotation", 0f, 360f);
-
ObjectAnimator anim3 = ObjectAnimator.ofFloat(tv_text, "scaleY", 1f, 3f, 1f);
-
ObjectAnimator anim4 = ObjectAnimator.ofFloat(tv_text, "translationY", 0f, 300f);
-
AnimatorSet animSet = new AnimatorSet();
-
-
AnimatorSet.Builder builder = animSet.play(anim1);
-
builder.with(anim2).after(anim3).before(anim4);
-
animSet.setDuration(5000);
-
animSet.start();
Image Caching Framework
For a detailed introduction to the picture caching framework, see<
Android Develops Note (77) Picture Caching Algorithms " Two common image caching frameworks, Picasso and Universal-Image-Loader, implement the Builder internal class of the builder pattern. Here is an example of the use code of the ImageLoader Configuration.Builder:
-
ImageLoaderConfiguration.Builder mBuilder = new ImageLoaderConfiguration
-
.Builder(this)
-
.threadPoolSize(3)
-
.threadPriority(Thread.NORM_PRIORITY - 2)
-
.denyCacheImageMultipleSizesInMemory()
-
.tasksProcessingOrder(QueueProcessingType.FIFO)
-
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
-
.memoryCacheSize(2 * 1024 * 1024)
-
.memoryCacheSizePercentage(13)
-
.memoryCacheExtraOptions(480, 800)
-
.diskCache(new UnlimitedDiskCache(imageCacheDir))
-
.diskCacheSize(50 * 1024 * 1024)
-
.diskCacheFileCount(100)
-
.imageDecoder(new BaseImageDecoder(false))
-
.writeDebugLogs()
-
;
-
ImageLoader.getInstance().init(mBuilder.build());