# Six principles of Object Orientation
- Single responsibility principle
Responsibility refers to the cause of class change. If more than one of the motivations of a class is changed, the class has more than one responsibility. The single responsibility principle states that a class or module should have only one reason for change. In layman’s terms, a class is responsible for only one job, encapsulating a set of highly related functions and data into a class.
- The open closed principle
Being open to extension means that the behavior of a module can be extended. As the requirements of the application change, we can extend the module to have new behaviors to meet those changes. Modifications are turned off, and the module’s source code does not need to be modified to extend the module’s behavior.
Popularly speaking, upgrade maintenance and new functions are added as far as possible through the extension of the system, rather than by modifying the existing source code.
- Richter’s substitution principle
Use “Abstraction” and “Polymorphism” to change the static structure of the design to dynamic structure, maintain the closure of the design. Wherever a base class can appear, a subclass must appear.
If you replace a base class object with a subclass object in software, the program will not generate any errors or exceptions, and vice versa. In the program try to use the base class type to define the object, and at run time determine its subclass type, with subclass object to replace the parent class object.
- Dependency inversion principle
High-level modules should not depend on low-level modules, they should all depend on abstractions. Abstraction should not depend on concrete implementation; concrete implementation should depend on abstraction. Programs rely on abstract interfaces, not concrete implementations. To put it simply, the requirement to program abstractions rather than implementations reduces the coupling between the client and the implementation module (the parameters passed between modules are declared as abstract types rather than concrete implementation classes).
- Interface Isolation Principle
The dependency of one class on another should be based on the smallest interface. The principle is to break up very large, bloated interfaces into smaller, more specific ones.
- Demeter principle
Also known as the least knowledge principle, one object should know as little as possible about other objects. In layman’s terms, a class should know the least about the classes it needs to couple or call, care nothing about the internal implementation of the class being coupled or called, and only call the methods you provide.
Let’s start learning design patterns… #1. Singleton
Function:
Ensure that only one instance of a Class exists in a Java application.
Benefits:
Because the singleton pattern has only one instance in memory, memory overhead is reduced.
The singleton mode can avoid multiple resource usage. For example, when a file is written, only one instance exists in the memory. Therefore, simultaneous write operations on the same resource file are avoided.
Singleton mode allows the system to set global access points, optimize and share resource access.
Usage:
A single-threaded operation to establish a directory database connection
An instance object that needs to be accessed frequently
##1.1 Usage method
The first form:
Private static Singleton instance = null; private static Singleton instance = null; /* Private Singleton() {} private Singleton() {} The initial Singleton is called the first time, and instead of regenerating it as a static method, Public static Singleton getInstance() {if (instance == null) {instance = new Singleton(); } return instance; }}
Copy the code
But there’s a problem, it’s out of sync! In the case of frequent reads and writes to database objects, the problem of out-of-sync becomes significant.
The second form:
Add a lock to getInstance method since it is not synchronized. We know that methods and code blocks can be synchronized using the synchronized keyword, so:
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
Copy the code
or
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
return instance;
}
Copy the code
Get Singleton instance:
Singleton.getinstance ().method ()
Copy the code
# # the Singleton in android 1.2
InputMethodManager for soft Keyboard management
Source code (the following source code is 5.1) :
205 public final class InputMethodManager { //......... 211 static InputMethodManager sInstance; / /... 619 public static InputMethodManager getInstance() { 620 synchronized (InputMethodManager.class) { 621 if (sInstance == null) { 622 IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); 623 IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); 624 sInstance = new InputMethodManager(service, Looper.getMainLooper()); 625 } 626 return sInstance; 628 627}}
Copy the code
A second singleton pattern of synchronized blocks of code (which may involve multithreading) is used, along with the AccessibilityManager (View gets distribution of clicks, focus, text changes, etc.), Debugging of the whole system, locating problems, etc.) BluetoothOppManager, etc.
There are also singleton implementations of synchronous methods, such as CalendarDatabaseHelper
307 public static synchronized CalendarDatabaseHelper getInstance(Context context) { 308 if (sSingleton == null) { 309 sSingleton = new CalendarDatabaseHelper(context); 310 } 311 return sSingleton; 312}
Copy the code
Note that Application is not a singleton pattern
44 public class Application extends ContextWrapper implements ComponentCallbacks2 { 79 public Application() { 80 super(null); 81}
Copy the code
In the Application source code, its constructor is public, which means that multiple Application instances can be generated. But why can Application implement only one instance of an APP? Take a look below:
In ContextWrapper’s source:
50 public class ContextWrapper extends Context {
51 Context mBase;
52
53 public ContextWrapper(Context base) {
54 mBase = base;
55 }
64 protected void attachBaseContext(Context base) {
65 if (mBase != null) {
66 throw new IllegalStateException("Base context already set");
67 }
68 mBase = base;
69 }
Copy the code
The ContextWrapper constructor passes in a null base, even if there are multiple Application instances, but no information is bound by attach().
But it is of no damn use
#2. Factory mode
Define an interface for creating objects and let subclasses decide which class to instantiate. The factory method delays the instantiation of a class to its subclasses. Manage and instantiate implementation classes of the same interface
Suppose we have a requirement like this:
Animal Animal, it has the behavior move(). There are two implementation classes cat and dog. We designed a factory model for unified management and creation. Meanwhile, the two subclasses have their own behaviors, Cat has eatFish() and Dog has eatBone().
Structure:
Animal interface:
interface animal {
void move();
}
Copy the code
Cat:
public class Cat implements Animal{ @Override public void move() { // TODO Auto-generated method stub System.out.println(" I'm a fat cat, I don't like to move "); } public void eatFish() {system.out.println (" eatFish "); }}
Copy the code
Dog class:
public class Dog implements Animal{ @Override public void move() { // TODO Auto-generated method stub System.out.println(" I am a dog, run fast "); } public void eatBone() {system.out.println (" eatBone "); }}
Copy the code
Now you can create a Factory class (factory.java) to manage and create instance classes.
Public class Factory {public static Cat produceCat() {return new Cat(); } public static Dog produceDog() { return new Dog(); } // There can also be a method, by passing the argument, switch implementation}
Copy the code
Use:
Animal cat = Factory.produceCat();
cat.move();
//-----------------------------
Dog dog = Factory.produceDog();
dog.move();
dog.eatBone();
Copy the code
The factory model is widely used in the industry. If all new objects are generated, animal can have many other sons as the project expands, and of course sons will have sons, as well as modifications to the previous code (such as adding instances of later sons), which would be a mess to manage.
Animal cat = Factory.produceCat();
Copy the code
This instantiates Animal but does not refer to specific subclasses of Animal (reducing the coupling between them), thus achieving encapsulation and reducing the chance of incorrect modifications.
The object-oriented principles of Java, Encapsulation and Delegation tell us that the more you do something, the more likely it is to get wrong,
Generally speaking, such ordinary factories can meet basic needs. But if we want to create an Animal implementation class panda, we must add a method to produce Panda in the factory class. This violates the design principle of closures (open for extensions and closed for modifications), hence the abstract factory pattern.
##2.1 Abstract Factory
The abstract factory pattern provides an interface to create a series of related or interdependent objects without specifying their concrete classes. What you mean? Production is abstracted as an interface, with each instance class corresponding to a factory class (a normal factory has only one factory class), and all factory classes inheriting the production interface.
Production interface Provider:
interface Provider {
Animal produce();
}
Copy the code
Each product has its own CatFactory:
public class CatFactory implements Provider{ @Override public Animal produce() { // TODO Auto-generated method stub return new Cat(); }}
Copy the code
DogFactory:
public class DogFactory implements Provider{ @Override public Animal produce() { // TODO Auto-generated method stub return new Dog(); }}
Copy the code
Product production:
Provider provider = new CatFactory();
Animal cat =provider.produce();
cat.move();
Copy the code
Now we need to join Panda and directly create a New pandaFactory, so that our system is very flexible and has dynamic expansion function.
##2.1 Factory in Android
For example, the abstract factory implementation of AsyncTask:
Factory abstraction:
59public interface ThreadFactory {// Omitted for remarks 69 Thread newThread(Runnable r); 70}
Copy the code
Product abstraction (new Runnable is its implementation class) :
56 public interface Runnable {// Omitted for remarks 68 public abstract void run(); 69}
Copy the code
Implementation of factory class in AsyncTask:
185 private static final ThreadFactory sThreadFactory = new ThreadFactory() { 186 private final AtomicInteger mCount = new AtomicInteger(1); 187 188 public Thread newThread(Runnable r) { 189 return new Thread(r, "AsyncTask #" + mCount.getAndIncrement()); 190} 191};
Copy the code
We can create another similar factory that produces a specialized thread (multithreading) that is easily scalable. Of course, there are many other android applications (such as BitmapFactory) that you can check out.
#3. Adapter (Adapter mode)
Translate the interface of a class into another interface that the customer wants.
The first solution to combining two unrelated classes is to modify their interfaces if we don’t have the source code, or if we don’t want to modify their interfaces for an application. How to do?
Using Adapter, create a hybrid interface between the two.
Roles in patterns
Adaptee: A class that needs to be adapted.
Adapter: Converts the original interface into the target interface by wrapping an object that needs to be adapted.
Target: The interface expected by the customer. They can be concrete or abstract classes, or they can be interfaces.
Class Adaptee {public void specificRequest() {system.out.println (" specific classes "); // Class Adaptee {public void specificRequest() {system.out.println (" specific classes "); } // interface Target {public void request(); }
Copy the code
Implementation method:
(1) Object adapter (implemented by object combination)
Class Adapter implements Target{// Private Adaptee Adaptee; Public Adapter (Adaptee Adaptee) {this. Adaptee = Adaptee; } public void request () {/ / here is to use the delegate done special function enclosing adaptee. SpecificRequest (); Public class Client {public static void main(String[] args) {Target adapter = new Adapter(new Adaptee()); adapter.request(); }}
Copy the code
In the case where Target is not an interface but a concrete class, the Adapter inherits Target directly.
Class adapter pattern (using inheritance implementation)
Class Adapter extends Adaptee implements Target{public void Request() {super.specificRequest(); class Adapter extends Adaptee implements Target{public void Request() {super.specificRequest(); Public static void main(String[] args) {Target adapter = new adapter (); adapter.request(); }
Copy the code
If Target and Adaptee are both interfaces, and both have implementation classes. Adaptation can be accomplished by implementing two interfaces through Adapter. There is also a PluggableAdapters that can dynamically obtain one of several adapters. Using the Reflection technique, you can discover Public methods in a class dynamically.
advantages
The system needs to use existing classes, and this class interface does not meet the needs of the system. The adapter pattern allows for better reuse of these capabilities. Decouple the target class from the adapter class, and improve scalability by introducing an adapter class that reuses the existing adapter class without modifying the original code.
disadvantages
Too much use of adapters will make the system very messy, not easy to grasp as a whole. For example, it is obvious that interface A is called, but in fact it is internally adapted to the implementation of interface B. Don’t use adapters if you don’t have to, and refactor your system directly.
Adapter in Android
There are a lot of Adapters in Android, and this is something you use a lot. The Adapter is the bridge between the AdapterView View and the data. The Adapter provides access to the data and is responsible for generating a corresponding View for each item of data.
Adapter inheritance structure
BaseAdapter source code:
30public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { 31 private final DataSetObservable mDataSetObservable = new DataSetObservable(); 32 33 public boolean hasStableIds() { 34 return false; 35 } 36 37 public void registerDataSetObserver(DataSetObserver observer) { 38 mDataSetObservable.registerObserver(observer); 39 } 40 41 public void unregisterDataSetObserver(DataSetObserver observer) { 42 mDataSetObservable.unregisterObserver(observer); 43}
Copy the code
ListAdapter and SpinnerAdapter are Target, data is Adaptee, using object combination.
#4. Chain of Responsibility
This avoids coupling between the sender and receiver of the request by giving multiple objects the opportunity to process the request. Connect the objects into a chain and pass the request along the chain until an object processes it. The client making the request does not know which object on the chain ultimately handles the request, allowing the system to dynamically reorganize and assign responsibilities without affecting the client.
Small embodiment in programming:
if(a<10){
...
}
else if (a<20){
...
}
else if(a<30){
...
}
else{
...
}
Copy the code
The program must scan each branch in turn for judgment and find the corresponding branch for processing.
Advantages of the chain of responsibility model
It can reduce the coupling degree of the system (separation of requester and handler code), simplify the interconnection of objects, and increase the flexibility of assigning responsibilities to objects. It is also convenient to add new request handling classes.
Disadvantages of the chain of responsibility model
It is not guaranteed that the request will be received, and for a long chain of responsibilities, the processing of the request may involve multiple processing objects, which will affect the system performance to a certain extent, and it is not convenient for code debugging. It always starts with the header, which is the disadvantage of linked lists. ##4.1 Chain of Responsibility in Android
The transfer of various events such as touch and keystroke
Interested can have a look at this article View event distribution mechanism source analysis, I will not say more.
The Observer is an Observer.
Sometimes referred to as the publish/subscribe pattern, the observer pattern defines a one-to-many dependency that allows multiple observer objects to listen on a subject object simultaneously. The topic object notifies all observer objects when their state changes, enabling them to update themselves automatically.
One of the undesirable side effects of splitting a system into classes that work together is the need to maintain consistency between related objects. We don’t want things to be tightly coupled for consistency, which makes maintenance, extension, and reuse difficult. The observer resolves this kind of coupling (the dependency is not completely removed; the abstract notifier still relies on the abstract observer). .
The composition of the observer pattern
① Abstract Subject
It stores references to all observer objects in an aggregate, and each topic can have any number of observers. Abstract topics provide an interface to add and remove observer objects.
② Concrete theme (ConcreteSubject)
Store the relevant state to the specific observer object; All registered observers are notified when the internal status of a specific topic changes.
③ Abstract observers
Define an interface for all specific observers to update themselves when notified of the topic.
(4) ConcreteObserver
Implement the update interface required by the abstract observer role to reconcile its own state with the topic state.
Words pale, on the code:
Public interface Observer {public void update(String STR); }
Copy the code
Public class ConcreteObserver implements Observer{@override public void update(String STR) {// TODO Auto-generated method stub System.out.println(str); }}
Copy the code
Public interface Subject {public void addObserver(Observer Observer); public void removeObserver(Observer observer); public void notifyObservers(String str); }
Copy the code
Public class ConcreteSubject implements Subject{private List<Observer> List = new ArrayList<Observer>(); @Override public void addObserver(Observer observer) { // TODO Auto-generated method stub list.add(observer); } @Override public void removeObserver(Observer observer) { // TODO Auto-generated method stub list.remove(observer); } @Override public void notifyObservers(String str) { // TODO Auto-generated method stub for(Observer observer:list){ observer.update(str); }}}
Copy the code
Here are the test classes:
/** * @author fanrunqi */ public class Test {public static void main(String[] args) {// A theme ConcreteSubject eatSubject = new ConcreteSubject(); ConcreteObserver personOne = new ConcreteObserver(); ConcreteObserver personTwo = new ConcreteObserver(); // The observer subscribes to the theme eatsubject.addobServer (personOne); eatSubject.addObserver(personTwo); / / notice for supper eatSubject. NotifyObservers (" dinner "); }}
Copy the code
“What do you want to say about the code?” “No, it’s all in the code.” (⊙ O ⊙) Oh…
##5.1 Observer for Android
The Observer mode is also widely used in Android, most familiar with ContentObserver.
① Abstract class ContentResolver (Subject)
Registered Observer:
1567 public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
1568 ContentObserver observer, int userHandle)
Copy the code
Cancel observer:
1583 public final void unregisterContentObserver(ContentObserver observer)
Copy the code
Abstract Classes in ContentObserver (Observer)
94 public void onChange(boolean selfChange) { 95 // Do nothing. Subclass should override. 96 } 144 public void onChange(boolean selfChange, Uri uri, int userId) { 145 onChange(selfChange, uri); 146 } 129 public void onChange(boolean selfChange, Uri uri) { 130 onChange(selfChange); 131}
Copy the code
Observe changes to the database caused by a particular Uri, and do some processing accordingly (eventually the first function is called).
②DataSetObserver, which we use all the time without realizing it.
Let’s look at some of the BaseAdapter source code:
37 public void registerDataSetObserver(DataSetObserver observer) { 38 mDataSetObservable.registerObserver(observer); 39 } 40 41 public void unregisterDataSetObserver(DataSetObserver observer) { 42 mDataSetObservable.unregisterObserver(observer); 43}
Copy the code
The above two methods register and unregister a DataSetObserver instance to BaseAdater.
DataSetObserver DataSetObserver
24public void onChanged() {30 public void onChanged() {30 public void onChanged() {30 public void onChanged() onInvalidated() { 39 // Do nothing 40 } 41}
Copy the code
DataSetObserver is an observer, and once it discovers that there are variables in the BaseAdapter data, Through callback methods DataSetObserver. OnChanged and DataSetObserver onInvalidated to inform DataSetObserver implementation class.
The Builder pattern: Separates the construction of a complex object from its representation (as well as the construction of different representations) so that the same construction process can create different representations.
When a person is over 70 years old, he or she will go through these stages: infant, teenager, youth, middle age and old age. And everyone must be different in each stage. There are no two people in the world who have exactly the same life in these five stages, but it is certain that those who live to be over 70 years old have all experienced these stages. This is actually a classic example of the Builder pattern.
By encapsulating the complex internal creation internally, the caller can pass in only the builder and builder tools, and doesn’t care how the interior is built into the finished product.
The Builder mode usually includes the following roles:
①Builder: an abstract interface used to regulate the construction of the components of a product object.
(2) ConcreteBuilder: Implements the Builder interface, concretes the creation of various parts of complex objects for different business logic, and provides product instances after the construction process is completed.
③Director: a Director who calls on specific builders to create parts of a complex object, without reference to specific product information, but only to ensure that the parts of the object are created intact or in a certain order.
④Product: complex object to be created.
Difference from abstract factory: In the builder model, there is a mentor, the mentor manages the builder, the user connects with the mentor, and the mentor connects with the builder to get the product. That is, the build model can enforce a step-by-step build process.
Product and Part of the Product interface
Public interface Product {} Public interface Part {}
Copy the code
Builder:
Public Interface Builder {void buildPartOne(); Void buildPartTwo (); The Product getProduct (); }
Copy the code
ConcreteBuilder:
Public class ConcreteBuilder implements Builder {Part Part, Part two; Public void buildPartOne() {// Build code}; Public void buildPartTwo() {// Build code}; Public Product getProduct() {// Return the last assembled Product}; }
Copy the code
Director :
Public class Director {private Builder Builder; Public Director(Builder Builder) {this. Builder = Builder; } public void construct() {builder.buildPartOne(); Builder. BuildPartTwo (); }}
Copy the code
Build:
ConcreteBuilder builder = new ConcreteBuilder(); Director director = new Director(builder); // Start each part of the construct director.construct(); Product product = builder.getResult();
Copy the code
Advantages:
The client does not have to know the details of the internal composition of the product.
The concrete builder classes are independent of each other, which is great for system scaling.
Since the specific builder is independent, it is possible to refine the construction process without any impact on other modules.
Application situation:
When creating some complex objects, the order of construction between the internal components of these objects is stable, but the internal components of the object face complex changes.
The algorithm for the complex object to be created is independent of the components of the object and of the assembly method of the components.
##6.1 Builder in Android
The Builder Pattern is used for Android dialogs.
371 public static class Builder { 372 private final AlertController.AlertParams P; 373 private int mTheme; 393 public Builder(Context context, int theme) { 394 P = new AlertController.AlertParams(new ContextThemeWrapper( 395 context, resolveDialogTheme(context, theme))); 396 mTheme = theme; 397}
Copy the code
The Builder for AlertDialog is a static inner class that does not define an abstract interface to the Builder. Attribute will save in the Build of AlertDialog class member variable P (AlertController. AlertParams).
Builder class part of the method:
416 public Builder setTitle(int titleId) { 417 P.mTitle = P.mContext.getText(titleId); 418 return this; 419}
Copy the code
452 public Builder setMessage(int messageId) { 453 P.mMessage = P.mContext.getText(messageId); 454 return this; 455}
Copy the code
525 public Builder setPositiveButton(CharSequence text, final OnClickListener listener) { 526 P.mPositiveButtonText = text; 527 P.mPositiveButtonListener = listener; 528 return this; 529}
Copy the code
The show() method returns an instance of dialog combined with the above Settings
991 public AlertDialog show() { 992 AlertDialog dialog = create(); 993 dialog.show(); 994 return dialog; 995} 996} 997 998}
Copy the code
972 public AlertDialog create() {
973 final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
974 P.apply(dialog.mAlert);
975 dialog.setCancelable(P.mCancelable);
976 if (P.mCancelable) {
977 dialog.setCanceledOnTouchOutside(true);
978 }
979 dialog.setOnCancelListener(P.mOnCancelListener);
980 dialog.setOnDismissListener(P.mOnDismissListener);
981 if (P.mOnKeyListener != null) {
982 dialog.setOnKeyListener(P.mOnKeyListener);
983 }
984 return dialog;
985 }
Copy the code
Simple construction:
New Alertdialog.Builder (context).setTitle(" title ").setMessage(" message box ").setpositiveButton (" OK ", null).show();
Copy the code
#7. Memento
The memo mode, also called the Snapshot Pattern or Token mode, is the behavior mode of objects.
A memo object is an object that stores a snapshot of the internal state of another object. The purpose of the memo pattern is to Capture, externalize, and store an object’s state without breaking encapsulation, so that the object can be restored to its stored state at a later time. The memo pattern is often used with the command pattern and the iteration subpattern.
There are three roles involved in the memo mode:
Originator: the Originator is responsible for creating a Memento to record its internal status at the current time. The Memento can be used to restore the internal status. Originator determines which internal states of the Originator are stored by Memento as needed.
(2) Memento: Stores the internal state of an Originnator object and prevents Originnator objects from accessing the Memento. The Memento has two interfaces. The Caretaker only sees the narrow interface of the Memento and passes the Memento to other objects.
E.g. The Caretaker keeps the Memento and does not operate or check the contents.
public class Originator { private String state; Public Memento createMemento(){return new Memento(state); } public void restoreMemento(Memento Memento){this.state = Memento. GetState (); } public String getState() { return state; } public void setState(String state) { this.state = state; System.out.println(" current status: "+ this.state); }}
Copy the code
public class Memento { private String state; public Memento(String state){ this.state = state; } public String getState() { return state; } public void setState(String state) { this.state = state; }}
Copy the code
public class Caretaker { private Memento memento; /** * Memento retrieveMemento(){return this.memento; } public void saveMemento(Memento Memento){this.memento = Memento; }}
Copy the code
Use:
Originator o = new Originator(); Caretaker c = new Caretaker(); // Change the state of the responsible object. Setstate ("On"); C.savememento (o.creatememento ()); // Change the status of the initiator. Setstate ("Off"); // Restore the state of the originator object.
Copy the code
Back up the status of an object without knowing its internal structure for later restoration.
##7.1 Memento for Android
The onSaveInstanceState and onRestoreInstanceState methods store the state of the Activity through serialized data structures called bundles (the equivalent of memos). These two methods don’t care about the data structures stored in the bundles.
Take a look at the source code:
1365 protected void onSaveInstanceState(Bundle outState) {
1366 outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
1367 Parcelable p = mFragments.saveAllState();
1368 if (p != null) {
1369 outState.putParcelable(FRAGMENTS_TAG, p);
1370 }
1371 getApplication().dispatchActivitySaveInstanceState(this, outState);
1372 }
Copy the code
1019 protected void onRestoreInstanceState(Bundle savedInstanceState) { 1020 if (mWindow ! = null) { 1021 Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG); 1022 if (windowState ! = null) { 1023 mWindow.restoreHierarchyState(windowState); 1024} 1025} 1026}
Copy the code
#8. Prototype
Prototype mode, which can quickly clone a new object that is similar to an existing one. It works like this: By passing a prototype object to the creation object, the creation object performs the creation by asking the prototype objects to copy themselves.
Deep copy and shallow copy. Deep copy refers to making a new copy of the referenced object within the object and referring to the new referenced object as the copied object (read twice).
One notable feature of the common use of stereotype patterns is the Clone () method that implements cloneable.
In the Intent source:
4084 @Override 4085 public Object clone() { 4086 return new Intent(this); 4087}
Copy the code
Here the Intent implements the prototype copy by implementing the Cloneable interface.
##9. Strategy (Strategy pattern) definition: there are a series of algorithms, each algorithm is encapsulated (each algorithm can be encapsulated into a different class), each algorithm can be replaced, the Strategy pattern allows the algorithm to change independently of the customers using it.
Example: a DVD player, you insert what disc, can play what movie. Property animation, set different interpolator objects, you can get different change curves. Return value parsing, which converts binary data into data in any format, such as String, Json, or XML, depending on the parser you pass in.
In fact, the strategy pattern is a perfect embodiment of polymorphism.
The implementation of different animations in Android mainly depends on Interpolator.
401 public void setInterpolator(Interpolator i) { 402 mInterpolator = i; 403}
Copy the code
##10. Template
Definition: Defines the framework of an algorithm in an operation, deferring steps to subclasses so that subclasses can redefine specific steps of an algorithm without changing the structure of the algorithm. The implementation process is determined, and the implementation details are handled by subclasses. The lifecycle is familiar to all of us. It is a typical Template pattern. In the case of the specific process, the methods that we want to copy the lifecycle and implement those functions are implemented by subclasses that inherit the activity.
The key is that there must be a concrete execution process, such as AsyncTask.
##11. Proxy
Definition: Provides a proxy for other objects to control access to that object. Agency: There is an intermediate layer between the starting point and the destination.
Application: Android cross-process communication. Binder mechanisms are recommended.
##12. Interpreter mode
Define the grammar of the language and build an interpreter to interpret sentences in the language.
For example, Android uses PackageManagerService to parse the Activity, service and other attributes defined in androidmanifest.xml.
##13. State
Behavior is determined by the states, different states have different behaviors.
Note: The behavior of the state pattern is parallel and non-replaceable, while the behavior of the policy pattern is independent and interchangeable.
Embodiment: Different states perform different behaviors. When WIFI is on, it automatically scans the surrounding access points and displays them in the form of a list. Empty when wifi is off.
##14.
We have a lot of commands, put them in a drop-down menu, and the user selects the specific Command by selecting the menu first. This is the Command mode.
Originally, the user (caller) invokes these commands directly, opens the document on the menu, directly points to the code that opens the document, uses the Command mode, adds an intermediary between the two, breaks this direct relationship, and at the same time, isolates the two, basically has no relationship. Obviously, the benefits of this approach are consistent with the characteristics of packaging, reducing coupling, and improving code robustness, maintainability, and reuse. Command is the typical pattern that will encapsulate behavior, and Factory is the pattern that will be created to encapsulate.
Android’s underlying logic forwards events using Command mode.
##15. Iterator
Provides a way to access elements in a container object sequentially without exposing the internal representation of the object.
Application:
The Iterator class in Java.
Cursor in Android.
cursor.moveToFirst();
Copy the code
##16. Composite
Objects are organized in a tree structure to achieve a partial-whole hierarchy, so that clients can use single objects and combined objects consistently.
Android View structure is a tree structure, each ViewGroup contains a series of views, and the ViewGroup itself is the View. This is a very typical combination pattern in Android. ##17. Flyweight (Share/Share mode)
Definition: Avoid the overhead of having a large number of small classes with the same content (such as memory), so that everyone can share a class (metaclass).
The principles of object-oriented languages is that everything is an object, but if use truly, object number may sometimes seem to be very big, such as word processing software, if every word as an object, thousands of words, the number of objects is thousands of, there is no doubt that the memory cost, so we still need to “seeking common ground while putting aside differences”, find out the object group have in common, design a metaclass, Encapsulation of classes that can be shared. In addition, some characteristics are non-shareable depending on the context, which reflects the intrinsic and extrinsic characteristics of Flyweight.
To put it plainly, it is to pinch an original model, and then create specific models with different characteristics for different situations and environments. Obviously, different new objects need to be created here, so Factory mode is often used in Flyweight mode. The internal state of a Flyweight is shared, and the Flyweight Factory is responsible for maintaining a Flyweight pool(mode pool) to hold objects of the internal state.
Flyweight mode is a mode that improves application efficiency and performance, making applications run much faster. For example, if you want to read a list of strings from a database, many of which are duplicated, you can store these strings in a Flyweight pool (pool).
Message.obtain() in Android thread communication, message.obtain () takes reusable messages from the Message pool each time a Message is retrieved, avoiding the creation of a large number of Message objects. # # the last
So the question is, what are design patterns?
The design pattern is the abstraction of the solution to the problem encountered in the actual programming.