preface
This whole design pattern thing, it sounds really weird. Sometimes it seems like a mystery. Most of the coding may not consider how to use the design to code.
If you’re an outsourcer, get out when you’re done. It’s possible that you really don’t need any design patterns, if you meet the functionality. If you are a developer or code maintainer with product iterations. Maybe you’ve had the experience of teasing the code behind your back about how messy it really is.
In the process of application development, the most difficult thing is not to complete the application development work, but to make the application system embrace the change in the subsequent upgrade and maintenance. Embracing change means maintaining high scalability, high cohesion, and low coupling without compromising the stability of the system, and maintaining a clear, flexible, and stable system architecture through changes from version to version.
Although in the actual development, we should suffer from the torture and destruction of the product, and need to complete the function and go online in extremely limited research and development time. To rush things, Copy code here and paste a class there. If there are multiple projects, and even often move some functions in this project, that project transplant a module, to the last dry, bitter or their own.
Regardless of force majeure, we still need to maintain good coding habits, think before coding, and try to make the structure more flexible and less coupled. This paper is to sort out some coding design principles and design patterns for learning and review.
Object-oriented design principles
The principle of | define | instructions |
---|---|---|
Principle of single liability | For a class, there should be only one cause for change | It is difficult to divide the boundary of responsibility, and the principle of single responsibility should be satisfied as far as possible. Interfaces must be single-responsibility, and classes should be designed so that there is only one cause for change |
Richter’s substitution principle | All references to the parent class must be able to use its child class transparently | Using the Richter substitution principle in a project, you should try to avoid subclass individuality (having your own business implementation method) |
Dependency inversion principle | Dependencies between modules occur through abstraction, while no direct dependencies between implementation classes occur. Their dependencies are generated through interfaces or abstract classes | As far as possible, every class should have an interface, an abstract class, or both. As far as possible, no class should be derived from a concrete class |
Dependency inversion principle | Dependencies between modules occur through abstraction, while no direct dependencies between implementation classes occur. Their dependencies are generated through interfaces or abstract classes | As far as possible, every class should have an interface, an abstract class, or both. As far as possible, no class should be derived from a concrete class |
Interface Isolation Principle | A client should not rely on interfaces it does not need, and dependencies between classes should be based on the smallest interface | The interface isolation principle defines interfaces as well as classes, and interfaces and classes are organized using atomic interfaces and atomic classes as much as possible |
Demeter principle | An object should know the least about the classes it needs to couple or call, and try not to expose too many public methods and non-static public variables | The core concept of Demeter’s law is the decoupling between classes. Increasing the reuse rate of classes may produce a large number of transfer or jump classes, leading to the increase of system complexity |
Open and closed principle | Objects in software (classes, modules, functions, and so on) should be open for extension, but closed for modification | Constrains extensions through interfaces or abstract classes, encapsulates changes, and opens the boundaries of extensions |
For details, see: Design Patterns – Six Principles of Object-oriented design
Design patterns
Common design patterns in code
Design patterns | shorthand | example | Break down |
---|---|---|---|
The singleton pattern | Ensure that there is only one instance of a class, and that you instantiate it yourself and make it available to the entire system. Ensure that a class has one and only one object to avoid creating multiple objects that consume too many resources | In actual development, many database Dao operations or services are directly singletons, so attention should be paid to thread safety and memory leakage problems | The singleton pattern |
Builder model | The Builder pattern is a creation pattern that creates a copy object step by step, allowing the user to have more fine-grained control over the construction flow of the object without knowing the details of the internal build | New Alertdialog.Builder (self).setTitle(” listbox “).setitems (new String[] {” listitem 1″,” listitem 2″,” listitem 3″}, Null).setnegativeButton (” Confirm “, null).show(); The Builder mode can also be used to control Activity startup constructs that have complex parameters | Builder model |
Adapter mode | The adapter pattern transforms a class at an interface into another interface that the client expects, thus enabling two classes to work together that would otherwise not work together due to interface mismatches | ListView as an important control, it needs to be able to display a variety of views (ItemView), each person needs to display different effects. Android adds an Adapter layer to isolate the changes, abstracts the ListView’s interface to the Item View, and calls the Adapter interfaces inside the ListView to perform layout operations. In this way, only the user implements the Adapter interface, and sets the Adapter to the ListView. The ListView can display each item of data according to the UI effect, quantity, and data set by the user | Adapter mode |
Observer model | The Observer pattern is a highly used pattern and is most commonly used in GUI systems, subscription-publish systems. Because an important function of this pattern is decoupling, it decouples the observed from the observer, making them less dependent on each other | Broadcast, EventBus, Rxjava, some upload and download progress callback listener | Observer model |
The appearance model | Appearance mode (Facade) in the development process of using frequency is very high, especially in the present stage various third party SDK is in our surrounding, and will use the SDK large probability model appearance, through a class appearance makes the interface has a unity of the whole system of high-level interface, it can reduce the use cost of users, It also hides a lot of implementation details from users | For example, Context can unify the scope of many system resources, and image libraries and network libraries used in actual development can provide a unified Facade to avoid global impact | The appearance model |
Often used but unknown design patterns
Design patterns | shorthand | example | Break down |
---|---|---|---|
Template pattern | Define an algorithm framework in an operation and defer steps to subclasses so that subclasses can redefine specific steps of an algorithm without changing the structure of that algorithm | When using AsyncTask, we know to put time-consuming methods in doInBackground (Params… In params, if you want to do something similar to initialization before doInBackground, you can uninstall the onPreExecutre method. When doInBackground completes, the onPostExecutre method will be executed | Template pattern |
The mediator pattern | This pattern transforms a many-to-many relationship between objects into a one-to-many relationship | An Android Activity is essentially an intermediary mode, where views interact with each other in a unified manner. (It is possible to click a Button and have an ImageView change images, but this logic is not written in the Button.) | The mediator pattern |
Chain of Responsibility model | Chain of responsibility is one of behavioral design patterns. 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 handles it | A similar implementation in Android source code is the distribution of touch events. Each time the user touches the screen, Android wraps the corresponding event as an event object and distributes it from the top of the ViewTree down. A recursive call to a ViewGroup event post is similar to a chain of responsibilities. Once the responsible person is found, the responsible person will hold and consume the event, which is reflected in the setting of the return value of the View’s onTouchEvent method. If onTouchEvent returns false, That means the current View will not be a clone of the event and will not hold on it; If true, the opposite is true, and the View holds the event and does not pass it out again | Chain of Responsibility model |
Decorative pattern | The decorator pattern, also known as the wrapper pattern, is one of the structural design patterns that dynamically extends the functionality of objects in a way that is transparent to the client, and is one of the alternatives to inheritance. Add some extra responsibilities to an object dynamically | Context itself is a pure Abstract class with two concrete implementation subclasses: ContextImpl and ContextWrapper. The ContextWrapper class is just a wrapper, and the ContextWrapper constructor must contain an actual Context reference, ContextWrapper also provides attachBaseContext () to specify the actual Context in the ContextWrapper object. Any method that calls the ContextWrapper object is redirected to the actual Context it contains | Decorative pattern |
Portfolio model | The composite pattern, also known as the partial overall pattern, is one of the structural design patterns. The composite pattern is relatively simple. It treats a group of similar objects as one object, combines objects according to a tree structure, and then provides a unified method to access the corresponding objects | There is a very classic implementation of composition patterns in Android source code that we use almost every day, and that is the nested composition of views and Viewgroups | Portfolio model |
Memo mode | Memo mode is a behavior mode that holds the current state of an object and can be restored to that state again later. The memo mode is implemented in such a way that the stored object states cannot be accessed by objects from outside. The purpose is to protect the integrity of the stored object states and the internal implementation from being exposed to the outside | In Android development, stateful mode applications are Android stateful applications, namely onSaveInstanceState and onRestoreInstanceState. These methods are called when an Activity exits abnormally and is killed by the system at a later time, giving developers a chance to store information about the Activity and recover the data the next time the Activity is relaunched | Memo mode |
The flyweight pattern | Sharing mode is an important way to implement pooling technology. Using shared objects can effectively support a large number of fine-grained objects | Database connection pool, long connection pool | The flyweight pattern |
Iterator pattern | The iterator pattern provides a way to access the elements of a container object sequentially without exposing the object’s internal representation | Traversal of various collections in the JDK | Iterator pattern |
Other Design Patterns
Design patterns | shorthand | Break down |
---|---|---|
The factory pattern | The factory pattern is one of the creative design patterns. Define an interface for user-created objects and let subclasses decide which class to instantiate. The factory pattern is an alternative to new, so it can be used wherever objects need to be generated | The factory pattern |
Abstract Factory pattern | Abstract factories are also one of the creative design patterns. Provides an interface for creating a set of related or interdependent objects without specifying their concrete classes. The abstract factory pattern can be used when a family of objects has the same constraints | Abstract Factory pattern |
The proxy pattern | Provides a proxy for other objects to control access to that object, with static code and dynamic proxies | The proxy pattern |
The prototype pattern | Specify what kind of objects to create with prototype instances, and create new objects by copying these prototypes | The prototype pattern |
The strategy pattern | The policy pattern defines a series of algorithms, encapsulates each algorithm, and makes them interchangeable. The policy pattern lets the algorithm change independently of the customers that use it | The strategy pattern |
Visitor pattern | Encapsulates operations that operate on elements of a data structure and defines new operations that operate on those elements without changing the data structure | Visitor pattern |
The state pattern | The behavior in the state mode is determined by the state, and different states have different behaviors. The structure of state patterns and policy patterns is almost identical, but their purpose and nature are completely different. The behavior of the state pattern is parallel and non-replaceable, while the behavior of the policy pattern is independent and interchangeable | The state pattern |
Interpreter mode | The interpreter pattern is a less commonly used behavior pattern that provides a way to interpret the syntax or expressions of a language by defining an expression interface through which to interpret a particular context | Interpreter mode |
Bridge pattern | Bridge mode, also called bridge mode, is one of structural design modes. Decouple the abstraction from the implementation so that the two can vary independently | Bridge pattern |
conclusion
Adornment mode, proxy mode, appearance mode difference
The proxy pattern focuses on isolation restrictions, focusing on controlling access to objects so that outsiders cannot access your actual calling objects, such as permission controls. The relationship between proxies and real objects is usually determined at compile time. Decoration mode focuses on the extension of functionality, focusing on dynamically adding methods to an object to achieve more functionality within the same method. Decorators can be constructed recursively at run time. The adapter pattern focuses on interface compatibility. The appearance pattern focuses on the integration and uniform adaptation of multiple classes.
Recommended books
“Zen of Design Patterns” “Android source code design pattern analysis and combat”
about
Welcome to pay attention to my personal public number
Wechat search: Yizhaofusheng, or search the official ID: Life2Code
- Author: Huang Junbin
- Blog: junbin. Tech
- GitHub: junbin1011
- Zhihu: @ JunBin