Writing in the front
- Introduction to books: While respecting the original intention of “Design Patterns”, this book comprehensively introduces 16 commonly used design patterns that are more suitable for JavaScript programmers according to the characteristics of JavaScript language, and explains the basic knowledge of JavaScript object-oriented and functional programming. This paper introduces the object-oriented design principle and its embodiment in the design pattern, and also shares the object-oriented programming skills and the code reconstruction in the daily development. This book will teach you how to apply classic design patterns to JavaScript to write beautiful, efficient, structured, and maintainable code.
- My brief comment: This book mainly focuses on some design patterns and design principles in JavaScript, each pattern is explained with life examples, appropriate, easy to understand. However, it is advisable to read a book on design patterns only after you have some programming experience and project experience.
- !!!!! At the end of the article there are PDF books, notes mind map, with the book code package download address, please help yourself! To read all notes in the book Intensive Series, please move: Recommended favorites -JavaScript Book Intensive Notes Series navigation
Chapter 1 object-oriented JavaScript
- JavaScript does not provide class inheritance in traditional object-oriented languages, but implements object to object inheritance in the form of prototype delegation. JavaScript also does not provide support for abstract classes and interfaces at the language level
1.1. Dynamically typed languages and duck types
- Statically typed languages determine the type of a variable at compile time, whereas dynamically typed languages do not have a type until the program is run, after the variable has been assigned a value
- A popular term for the duck type is: if it walks like a duck and quacks like a duck, it is a duck
- The duck type instructs us to focus only on the behavior of the object and not on the object itself, i.e., on HAS-A, not IS-A
- The concept of duck types is crucial in the object-oriented design of dynamically typed languages. Using the duck type idea, we can easily implement one principle in dynamically typed languages without the aid of supertypes: interface oriented programming, not implementation oriented programming
1.2. Polymorphism
- The actual meaning of polymorphism is that the same operation on different objects can produce different interpretations and different execution results. In other words, when you send the same message to different objects, they will give different responses based on the message
- A piece of “polymorphic” JavaScript code: The idea behind polymorphism is to separate “what” from “who does it and how”, i.e., “things that don’t change” from “things that can change”
- Type checking and polymorphism: Statically typed object-oriented languages are often designed to be upward-transitive: when assigning a value to a class variable, the type of the variable can use either the class itself or a superclass of the class
- JavaScript polymorphism: The idea of polymorphism is to separate the “what” from the “who does it”. To achieve this, it boils down to decoupling the coupling between types. In JavaScript, techniques such as uptransitions are not required to achieve polymorphic results;
- The role of polymorphism in object-oriented programming: The fundamental role of polymorphism is to eliminate conditional branching statements by converting procedural conditional branching statements into object polymorphism
- Design Patterns and Polymorphism: GoF’s “Design Patterns” is entirely from the perspective of object-oriented design, through the repeated use of encapsulation, inheritance, polymorphic composition and other techniques, extracted some reusable object-oriented design techniques
1.3. Encapsulation
- The purpose of encapsulation is to hide information
- Encapsulating data: JavaScript does not provide support for the keywords private, protected, and public. We rely on the scope of variables to implement encapsulation features, and can only simulate public and private encapsulation
- Encapsulation implementation: The purpose of encapsulation is to hide information. Encapsulation should be considered “any form of encapsulation”, that is, encapsulation not only hides data, but also hides implementation details, design details, and types of objects; Encapsulation loosens the coupling between objects, which communicate only through exposed API interfaces.
- Encapsulation type: Encapsulation type is an important encapsulation method in statically typed languages. In general, encapsulating types is done through abstract classes and interface classes; JavaScript itself is a type-fuzzy language. JavaScript doesn’t have the ability or the need to do much more to encapsulate types;
- Encapsulating Change: Design Patterns summarizes 23 design patterns. In terms of intent, these 23 design patterns can be divided into creative, structural, and behavioral patterns
1.4. Prototype patterns and JavaScript objects based on prototype inheritance
- The prototype pattern is not only a design pattern, but also known as a programming paradigm
- Using the clone prototype pattern: The key to the implementation of the prototype pattern is whether the language itself provides the Clone method. ECMAScript5 provides the object. create method, which can be used to clone objects
- Cloning is a means of creating objects: however, the real purpose of the prototype pattern is not to have an identical object, but to provide a convenient way to create a certain type of object, cloning is just the process and means of creating that object
- Experience Io language: There is no concept of classes in JavaScript, objects are not created from classes, all JavaScript objects are cloned from an object; JavaScript’s prototype-based object-oriented system references Self and Smalltalk;
- Some rules of prototype programming paradigm: Io language and JavaScript language, based on prototype chain delegation mechanism is the essence of prototype chain inheritance; An important feature of prototype programming is that when an object cannot respond to a request, it delegates the request to its own prototype. The prototype programming paradigm includes at least the following basic rules (all data is an object; To get an object, not by instantiating the class, but by finding an object as a prototype and cloning it; An object remembers its prototype; If an object cannot respond to a request, it delegates the request to its own prototype.)
- Prototype inheritance in JavaScript: In fact, the root Object in JavaScript is the Object.prototype Object. Prototype is an empty Object; JavaScript functions can be called either as normal functions or as constructors. When a function is called with the new operator, the function is a constructor. The process of creating an Object with the new operator is actually just cloning the Object.prototype Object and doing some additional operations. As far as JavaScript is concerned, you can’t really say that objects have archetypes, only that the object’s constructor has archetypes. A better way to say that an object delegates requests to its own prototype is to say that the object delegates requests to its constructor’s prototype; Although JavaScript objects are originally cloned from object. prototype, Object constructor prototypes are not limited to Object.prototype, but can dynamically point to other objects; Note that the prototype chain is not infinite;
- Archetypal patterns are both design patterns and programming generics that form the foundation of JavaScript as a language
Chapter 2 This, Call and apply
2.1. This
- In contrast to other languages, JavaScript’s this always refers to an object, which object is dynamically bound at runtime based on the execution environment of the function, not the environment in which the function was declared
- The reference to this can be roughly divided into four categories (method calls as objects; A call as a normal function; Constructor call; Function.prototype.call or function.prototype. apply);
- 1. Method calls as objects: this refers to this object
- 2. Called as a normal function: this refers to the global object; In strict mode of ECMAScript5, this in this case is already specified not to refer to a global object, but to undefined;
- Constructor call: When a function is called with the new operator, the function always returns an object. Normally, this in the constructor refers to the object returned
- . 4. The Function prototype. Call or Function. The prototype, the apply call (can dynamically change into this Function; The Call and Apply methods are a good example of the functional language nature of JavaScript. Almost every time you write functional language style code in JavaScript, call and Apply are indispensable.)
- Missing this: When obj.getName is referred to by another variable getName2, and getName2 is called, it is a normal function call. This refers to the global window, so the result of the program is undefined
2.2. The call and apply
- ECMA3 defines two methods for Function prototypes: function.prototype. call and function.prototype. apply
- The difference between call and apply is only in the form of the arguments passed in; Apply takes two arguments. The first argument specifies the point to the this object in the function body, and the second argument is a collection with a lower index. The number of arguments that call passes is not fixed. The first argument also represents the “this” point in the function. From the second argument, each argument is passed to the function in turn. When a function is called, the JavaScript interpreter does not discriminate between the number, type, and order of parameters and arguments; JavaScript arguments are internally represented as an array. In this sense, apply is more used than Call, and we don’t care how many arguments are passed to the function;
- Use of call and apply: 1. Redirect this (the most common use); . 2. The Function. The prototype bind (most advanced browsers implement the built-in Function. The prototype. The bind, to this point) of the specified Function inside; 3. Borrow methods from other objects;
Chapter 3 closures and higher-order functions
- The originator of functional language is LISP. At the beginning of design, JavaScript referred to Scheme, one of the two dialects of LISP, and introduced features such as Lambda expressions, closures and higher-order functions
3.1. The closure
- The formation of closures is closely related to the scope and lifetime of variables
- Scope of a variable: Indicates the valid range of a variable
- Lifetime of a variable: The generation cycle of a global variable is permanent unless it is actively destroyed. Local variables declared in a function using the var keyword lose value when exiting the function. They are destroyed at the end of the function call.
- 1. Encapsulate variables (closures help to encapsulate “private” variables that do not need to be exposed globally). 2. Prolong the life of local variables;
- Closures and Object-oriented Design: In the JavaScript language’s ancestor, The Scheme language, there is not even a native object-oriented design, but you can use closures to implement a complete object-oriented system
- Implement the command pattern with closures: The intent of the command pattern is to encapsulate the request as an object to decouple the coupling between the initiator of the request and the receiver of the request
- Closures and memory management: The conventional wisdom is that closures leak memory, so minimize the use of closures; Local variables are supposed to be dereferenced when the function exits, but if the local variable is enclosed in the context of the closure, the local variable will survive forever. In the garbage collection mechanism based on the reference technology strategy, if a circular reference is formed between two objects, then neither object can be collected, but the memory leak caused by the circular reference is not caused by the closure per se;
3.2. Higher-order functions
- A higher-order function is one that satisfies at least one of the following conditions: 1. 2. The function is output as a return value. 3. High-order function implementation AOP; 4. Other applications of higher-order functions;
- 1. Functions passed as arguments: One of the most important applications is the common callback function; Array.prototype.sort takes a function that encapsulates the sort of Array elements;
- 2. Function as return value output: function as return value output application scenarios may be more, but also more can reflect the clever functional programming; 1. Determine the type of data, isType function; 2. GetSingle, example of singleton pattern;
- 3. High-order function implementation AOP: AOP (aspect oriented programming) is the main role of some functions unrelated to the core business logic module out of the function, these unrelated to business logic, including log statistics, security control, exception handling, etc.; AOP techniques can be implemented in the Java language through reflection and dynamic proxy mechanisms. In JavaScript, a dynamic language, AOP is easier to implement, which is JavaScript’s inherent ability. Adding responsibilities to functions using AOP is also a very special and clever decorator pattern implementation in the JavaScript language;
- 4. Other applications of higher-order functions: 1. 2. Uncurrying; 3. Function throttling; 4. Time-sharing function; 5. Lazy loading function;
Chapter 4 singleton pattern
- The singleton pattern is defined to ensure that a class has only one instance and provide a global access point to access it
- The singleton pattern is a common pattern, and there are some objects that we usually need only one, such as thread pool, global cache, window object in browser, and so on
4.1. Implement singleton pattern
- Implementing a standard singleton pattern is nothing more than a variable that indicates whether an object has been created for a class and, if so, returns the previously created object the next time an instance of the class is fetched
4.2. Transparent singleton pattern
- Implement a “transparent” singleton class from which users can create objects just like any other normal class
4.3. Implement singleton pattern with proxy
- Remove the code responsible for managing singletons
4.4. Singleton pattern in JavaScript
- Douglas Crockford has repeatedly called global variables the worst feature of JavaScript
- In an interview with Brendan Eich, the creator of JavaScript, he himself admitted that global variables were a design mistake, the result of not having enough time to think about something
- There are several ways to reduce naming pollution associated with global variables
- 1. Use namespaces: Proper use of namespaces does not eliminate global variables, but it can reduce the number of global variables
- 2. Use closures to encapsulate private variables: Encapsulate some variables inside closures, exposing only interfaces to communicate with the outside world
4.5. Lazy singleton
- Lazy singletons are instances of objects that are created only when needed
- Take WebQQ login floating window as an example: you can use a variable to determine whether the login floating window has been created
4.6. Generic lazy singleton
- Another problem with the previous section is that, in violation of the single responsibility principle, the logic for creating objects and managing singletons is placed inside the createLoginLayer object; Next time you need to create a unique iframe, script, etc. on a page to request data across domains, you must copy the code;
- Take the logic of how to manage singletons out of the original code
4.7 summary
- The singleton pattern is a simple but very useful pattern, especially the lazy singleton technique, where objects are created when appropriate and only one is created
- Even more wonderful, the responsibility for creating objects and managing singletons is split between two different methods, which together have the power of the singleton pattern
Chapter 5 strategy mode
- The definition of a strategy pattern is to define a series of algorithms, encapsulate them one by one, and make them interchangeable
5.1. Use the policy model to calculate bonuses
- Take the year-end bonus calculation as an example: 1. The initial code implementation of if judgment; 2. Use composition functions to reconstruct code; 3. Refactoring code using policy patterns;
- The strategy pattern refers to defining a set of algorithms and encapsulating them one by one. The theme of each design pattern is to separate the invariant from the changing, and the strategy pattern is no exception. The purpose of the strategy pattern is to separate the use of the algorithm from the implementation of the algorithm
- A policy-based program consists of at least two parts. The first part is a set of policy classes, which encapsulate the specific algorithm and are responsible for the specific calculation process. The second part is the Context class, which accepts a client’s request and then delegates it to a policy class
5.2.JavaScript version of the policy mode
- In fact, functions are also objects in the JavaScript language, so it is simpler and more straightforward to define strategy directly as a function
5.3. The embodiment of polymorphism in the strategy mode
5.4. Implement slow animation using strategy mode
- To achieve the principle of animation effect: animation is to put some gap between the original painting to play faster IDE frame number, to achieve visual animation effect; In JavaScript, you can animate an element by continuously changing one of its CSS attributes, such as left, top, and background-position.
- Ideas and some preparation: You need to write down some useful information in advance
- Get the ball moving:
Animate.prototype.start = function(propertyName, endPos, duration, easing){}
5.5. A more generalized “algorithm”
- By definition, policy patterns encapsulate algorithms. However, if the policy pattern is only used to encapsulate the algorithm, it is a bit of overkill
- In real development, we often spread the meaning of algorithms to mean that the policy pattern can also be used to encapsulate a set of “business rules”
5.6. Form verification
- The first version of form validation: multiple if judgments
- Refactoring form validation with policy mode: Create a Validator object and add some validation rules to the Validator object using the validator.add method
- Adds multiple validation rules to a text input field
5.7. Advantages and disadvantages of strategic patterns
- The policy pattern is a common and effective design pattern. This chapter provides Sanger examples to deepen our understanding of the policy pattern
- The advantages of the strategy pattern are summarized. The strategy pattern can avoid multiple conditional selection statements by using combination, delegation and polymorphism. The policy pattern provides perfect support for the open-closed principle, encapsulating algorithms in a separate strategy, making them easy to switch, easy to understand, and easy to extend; Algorithms in the policy pattern can also be reused elsewhere in the system to avoid many repetitive copy-and-paste patterns; Using composition and delegation in the policy pattern to give Context the ability to perform algorithms is a lighter alternative to yeshiva inheritance;
5.8. First-class function objects and policy patterns
- In fact, in languages like JavaScript, where functions are first-class objects, the policy pattern is built into the language itself, and we often use higher-order functions to encapsulate different behaviors and pass them to another function
5.9 summary
- In the policy pattern of JavaScript language, the policy class is often replaced by the function, so the policy pattern becomes an “invisible” pattern
Chapter 6 Agency mode
- The proxy pattern provides a proxy or placeholder for an object to control access to it
- The key to the proxy model is to provide a proxy object to control access to an object when it is inconvenient or not necessary for the client to directly access the object. After the proxy object does some processing of the request, it passes the request to the ontology object
6.1. The first example – The story of Xiao Ming chasing after MM
- Let xiao Ming and MM common friends to send flowers
6.2. Protect agents and virtual agents
- A protected proxy is used to control access to a target object by objects with different permissions, but it’s not easy to implement in JavaScript because you can’t tell who is accessing an object
- Virtual proxy is the most common proxy mode
6.3. Virtual proxy implements image preloading
- The common method of image preloading is to load the image asynchronously with a loading image, and then fill the image into the IMG node after the image is loaded
6.4. The meaning of agency
- All we really need is to set SRC for the IMG node, and preloading images is just the icing on the cake
- The role of the agent is shown here. The agent is responsible for preloading the image, and when the preloading operation is complete, the request is redirected to the ontology MyImage
6.5. Consistency of proxy and ontology interfaces
- The key is that both the proxy object and ontology provide setSrc methods externally. In the eyes of customers, the proxy object and ontology are consistent. The process of proxy taking over requests is transparent to users, who are not aware of the difference between the proxy and ontology
- In languages such as Java, agent and ontology needs to be explicitly implement the same interface, on the one hand, the interface ensures that they will have the same way, on the other hand, the programming to an interface to cater to the dependency inversion principle, through the interface up transformation, thus to avoid the compiler type checking, agent and ontology can be replaced to use in the future
- In dynamically typed languages like JavaScript, we sometimes use duck types to check whether both proxies and ontologies implement setSrc methods, and most of the time we don’t even check at all, relying entirely on programmer awareness, which has an impact on the robustness of the program
6.6. Virtual proxy merges HTTP requests
- File synchronization function
- The solution is to use a proxy function to collect requests over a period of time and finally send them to the server once
6.7. Application of virtual proxy in lazy loading
- Miniconsole.js open source project that wants to load when F12 is pressed to actively invoke the console
6.8. Cache proxy
- The cache proxy can provide temporary storage for some expensive operation results, and can return the previously stored operation results directly on the next operation if the parameters passed in are the same as before
- Example of caching proxy – compute product
- Caching proxies are used for Ajax asynchronous requests for data
- Common paging requirements, the same page of data should theoretically be pulled in the background only once, the pulled data is cached somewhere, the next time the same page is requested, the previous data can be used directly
6.9. Dynamically create proxies with higher-order functions
- Caching proxies can be created for various computation methods by passing in higher-order functions in a more flexible manner
6.10 Other Proxy Modes
- There are many variations of the proxy pattern: firewall proxy; Remote agent; Protection agent; Intelligent reference proxy; Write time copy agent;
6.11 summary
- The proxy pattern includes many subcategories, the most common in JavaScript development being virtual proxies and caching proxies
- When we write business code, we often don’t have to guess in advance whether we need to use proxy patterns or not, and we can write proxies only when we really find it inconvenient to access an object directly
Chapter 7 iterator pattern
- The iterator pattern provides a way to access the elements of an aggregate object sequentially without exposing the internal representation of the object
7.1. Iterators in jQuery
- The iterator pattern is nothing more than a loop through the elements of an aggregate object
7.2. Implement your own iterators
7.3. Inner and outer iterators
- Iterators can be divided into internal iterators and external iterators, which have their own applicable scenarios
- In some languages without closures, the implementation of the inner iterators themselves is quite complex
- An external iterator must explicitly request that the next element be iterated over
- Although external iterators are called in a relatively complex way, they are more practical and can meet more changeable needs
7.5. Inverse-order iterators
- The iterator pattern provides a way to loop through each element of an aggregate object, but it does not specify whether we traverse the aggregate object in order, backward, or middle order
7.6. Abort iterators
- The each convention of jQuery terminates the loop prematurely if the result of the callback returns false
7.7. Application examples of iterator pattern
- Obtain the corresponding upload component object based on the browser
7.8 summary
- The iterator pattern is a relatively simple pattern, so simple that it is often not considered a design pattern
Chapter 8 Publish and subscribe model
- The publisk-subscribe pattern, also known as the observer pattern, defines a one-to-many dependency between objects. When an object’s state changes, all dependent objects are notified
- In JavaScript development, we generally use the event model instead of the traditional publish-subscribe model
8.1. The publish-subscribe model in reality
- Example of sales: home buyers’ phone numbers are recorded in the sales office roster, the launch of the new property, sales MM will turn over the roster, traverse the above phone number, in turn to send a text message to inform them
8.2. The role of the publish-subscribe model
- The publish-subscribe pattern is widely used in asynchronous programming as an alternative to passing callbacks
- Publish-subscribe can replace hard-coded notification between objects, so that one object no longer explicitly calls an interface of another
8.3. The DOM events
- In fact, as long as we’ve ever tied event functions to DOM nodes, we’ve used publish-subscribe
- Subscribers can also be added or removed at will, and any additional subscribers will not affect the writing of the publisher’s code
8.4. Custom events
- How to implement the publish-subscribe model step by step: first, specify who will act as the publisher (such as a sales office); Then add a cached list to the publisher to store callback functions to notify subscribers (the sales office roster); When the message is finally published, the publisher iterates through the cached list, triggering the subscriber callback function in turn (iterating through the roster, texting one by one);
8.5. General implementation of the publish-subscribe pattern
- Take the publish-subscribe functionality out and put it in a separate object
8.7. Real life example – Website login
- The site has a header, nav navigation, message list, shopping cart, and more. One common prerequisite for these modules is that the user’s login information must be obtained using an Ajax asynchronous request
- More importantly, we don’t know what modules will need to use this user information in the future beyond header headers, NAV navigation, message lists, and shopping carts
- When rewritten in publish-subscribe mode, business modules interested in user information will subscribe to a successful login message event themselves. When the login is successful, the login module only needs to publish the successful login message, and the business side will start their respective business processing after receiving the message. The login module does not care about what the business wants to do, and does not want to know their internal details
8.8. Global publish-subscribe objects
- To buy a house is not necessarily to go to the sales office, we only need to submit the subscription request to the intermediary company, and the major real estate companies only need to release the house information through the intermediary company. In this way, we don’t care which real estate company the news comes from, we care if the news is received smoothly
- The publish-subscribe model can be implemented with a global Event object. Subscribers do not need to know which publisher the message comes from, and publishers do not know which subscribers the message will be pushed to. Events act as a kind of “intermediary”, connecting subscribers and publishers
8.9. Inter-module communication
- One problem to keep in mind is that if modules communicate with each other in too many global publish-subscribe modes, the module-to-module connections can be hidden behind. We end up not knowing which module the message is coming from, or which module the message is going to, which can cause some trouble in maintenance, perhaps because the purpose of a module is to expose interfaces to other modules to call
8.10. Must I subscribe before PUBLISHING
- In some cases, we need to save the message and re-publish it to subscribers when an object subscribes to it. Just like the offline message in QQ, the offline message is saved in the server, and the recipient can receive the message again after the next login
- In order to meet this requirement, we need to build a stored offline event stack, when events are published, if haven’t the subscriber to subscribe to this event, we’ll leave the publish event action wrapped in a function, the packaging function will be deposited in the stack, until finally have object to subscribe to this event, We will traverse the stack and execute these wrapper functions in turn, republishing the events inside
8.12.JavaScript implements the convenience of a publish-subscribe model
- Implementing a publish-subscribe model of its own in Java typically passes the subscriber object itself as a reference to the publisher object, and the subscriber object also provides a method called such as update that the publisher object can call when appropriate
- In JavaScript, we replace the traditional publish-subscribe model with a register callback function, which is much more elegant and simple
- In JavaScript, we don’t have to choose whether to use the push or pull model. The push model is where the publisher pushes all the changed state and data to subscribers at once when an event occurs. The pull model differs in that the publisher only notifies the subscriber that an event has occurred, and the publisher provides some public interface for the subscriber to actively pull data
8.13 summary
- The advantages of the publish-subscribe model are obvious. One is decoupling in time, but decoupling between objects
- It can be used both in asynchronous programming and in more loosely coupled code writing
- Cons: Creating a subscriber itself takes time and memory, and when you subscribe to a message, the message may never happen, but the subscriber will always be in memory. In addition, the publish-subscribe model can weaken the relationship between objects, but if overused, the necessary relationship between objects can be buried in the background, making it difficult for programs to track, maintain, and understand
Chapter 9 Command mode
9.1. Usage of command Mode
- Command mode is one of the simplest and most elegant modes. A command in command mode refers to an instruction that does something specific
- The command pattern is most commonly used when you need to send a request to some object without knowing who the recipient of the request is or what action is being requested. At this point, you want to design the program in a loosely coupled way so that the request sender and the request receiver can decouple from each other
9.2. Example of command mode – menu program
- The reason for using the command pattern here: After a button is clicked, a request must be sent to some object responsible for the specific behavior, which is the recipient of the request
- The theme of design patterns has always been to separate immutable transactions from things that change, and command patterns are no exception
9.3. Command mode in JavaScript
- In object-oriented design, the receiver of a command pattern is stored as a property of a command object, and the command. Execute method is the operation that executes the command
9.4. Cancel the command
- Command mode not only encapsulates the operation block, but also easily adds undo operations to the command object
- Undo is a very useful function in command mode. When we develop a go program, we can encapsulate the changes of each step of the chess piece into a command, so it is easy to realize the function of destroying the game
9.6. Command queues
- The life cycle of a command object is independent of the time when the initial request occurs. The execute method of a command object can be executed at any time the program is running. Even if the request to click a button has already occurred, our command object is still alive
9.7. Macros
- Macro command is a combination of command mode and composite mode
9.9 summary
- Unlike many other languages, JavaScript can easily implement command patterns with higher-order functions
- Command mode is an invisible mode in the JavaScript language
Chapter 10 Combination mode
- The composite pattern is to build larger objects from smaller children, which themselves may be made up of smaller grandchildren
10.1. Review macro commands
- A macro command object consists of a specific set of subcommand objects. In both cases, a execute method is used to execute the command
- In macroCommand’s execute method, the actual operation is not performed. Instead, it iterates through the leaf objects it contains, delegating the actual execute request to them
10.2. Use of the combined mode
- The composition pattern groups objects into a tree structure to represent a partial-whole hierarchy. In addition to representing tree structures, another advantage of the composite pattern is that it allows users to use individual and composite objects consistently through the polymorphic representation of objects
10.3. The process by which requests are passed through the tree
- In composite mode, requests always follow a logic as they pass through the tree
- As a customer, you only need to care about the composite object at the top of the tree, you just need to request this composite object, and the request will be passed down the tree to all the leaf objects
10.4. More powerful macro commands
- Base objects can be combined into more complex composite objects, which can be combined into more complex composite objects, and so on recursively, and the structure of the tree can support any amount of complexity
10.5. The role of abstract classes in composite patterns
- The biggest advantage of the composite pattern is that you can treat composite objects and base objects identically. The customer does not need to know whether the macro command being processed is a normal command, as long as it is a command and has the execute method, the command can be added to the tree
- In a dynamically typed language like JavaScript, where object polymorphism is inherent and there is no compiler to check the type of a variable, we usually don’t emulate a “weird” abstract class. The difficulty in implementing a composite pattern in JavaScript is to make sure that a composite object has the same method as a leaf object. This usually requires checking their interfaces with duck type ideas
- Implementing composite patterns in JavaScript seems to lack some rigor, and our code is not secure, but it can be developed more quickly and freely, which is both a weakness of JavaScript and its strength
10.6. Security issues arising from transparency
- The transparency of the composite pattern allows the requesting client to ignore the distinction between composite and leaf objects in the tree, but they are fundamentally different
10.7. Example of combined mode – Scan folders
- The relationship between folders and files is best described in the composite pattern. Folders can contain files as well as other folders, eventually forming a tree
- In the process of adding a batch of files, the customer does not have to distinguish whether they are files or folders. Newly added files and folders can easily be added to the original tree structure to work with existing objects in the tree
10.8. Some points to note
- 1. The combinatorial pattern IS not parent-child: the combinatorial pattern IS A has-A, not IS-A
- 2. Consistency of operations on leaf objects: In addition to the requirement that the composite object and the leaf object have the same interface, the combination mode also requires consistency of operations on a group of leaf objects
- 3. Bidirectional mapping
- 4. Use responsibility chain mode to improve the performance of combination mode
10.10. When to use composite mode
- Applies in two cases: represents a partial-whole hierarchy of objects; The customer wants to treat all objects in the tree uniformly;
10.11 summary
- The composite pattern allows us to create the structure of an object in a tree fashion. We can apply the same operations to composite objects as to individual objects
- The composite pattern is not perfect, and it can lead to a system in which every object looks pretty much like every other object/and their differences only become apparent at run time, which can make code difficult to understand
Chapter 11 is the template method pattern
- An inheritance based design pattern
11.1. Definition and composition of the template method pattern
- The template method pattern is a very simple pattern that can be implemented using inheritance alone
- The template method pattern consists of two parts, the first part is the abstract parent class, the second part is the concrete implementation child class.
- The algorithm framework of a subclass is usually encapsulated in an abstract superclass, including the implementation of some common methods and the execution order of all methods in the subclass. By inheriting this abstract class, subclasses also inherit the entire algorithm structure and can choose to override the methods of the parent class
11.2. First example -Coffee or Tea
- Make a cup of coffee first
- Make a pot of tea
- 3. Separate the similarities: They can all be sorted out in four steps: 1. 2. Brew drinks with boiling water; 3. Pour the drink into the glass; 4. Add seasoning
- The reason why it is called a template method is that the algorithm framework of the subclass is encapsulated in this method. It acts as an algorithm template to instruct the subclass to execute which methods in which order
11.3. An abstract class
- First of all, the template approach is a design pattern that relies heavily on abstract classes
- The role of abstract classes
- Abstract methods and concrete methods
- An example of implementing Coffee or Tea in Java
- JavaScript has no abstract class disadvantages and solutions: JavaScript does not provide syntactic support for abstract classes. The first function of abstract classes is to hide the concrete type of an object. Since JavaScript is a “type-fuzzy” language, hiding the type of an object is not important in JavaScript. On the other hand, when we use stereotype inheritance in JavaScript to emulate traditional class inheritance, there is no compiler to help us do any kind of checking, and there is no way to guarantee that subclasses will override “abstract methods” in their parent classes; In Java, the compiler guarantees that a subclass overrides its parent class’s abstract methods, but in JavaScript it doesn’t do these checks; There are two workarounds (the first is to simulate interface checking with the duck type to ensure that the subclass actually overrides the parent class’s methods; The second option is to make methods like beverage.prototype. brew throw an exception directly.)
11.4. Usage scenarios for the template method pattern
- The template method pattern is often used by architects to build the framework of a project. The architect sets the skeleton of the framework, and the programmer inherits the structure of the framework and fills in the blanks
11.5. Hook methods
- Hook methods can be used to solve this problem (to keep subclasses from being bound by a step), and placing hooks is a common means of isolating changes. We place hooks in mutable parts of the parent class. Hooks can have a default implementation, and it is up to the subclass to decide whether to “hook”. The result of the hook method determines the next part of the template method, which is the next direction of the program, and thus the program has the possibility to change
11.6. The Hollywood Principle
- Hollywood rule: Don’t come to me, I’ll call you
- Under the guidance of this principle, we allow the underlying components to tied himself to the high-level component, and high-level component will decide when, how to use these underlying components, high-level component treatment of underlying components, were treated with performing arts company new actors, “don’t call us, we will call you”
- When we write a program using the template method pattern, it means that the subclass gives up control of itself, and instead uses the parent class to tell the subclass, which methods should be called and when
- The Hollywood principles are often applied to other patterns and scenarios, such as publish-subscribe and callback functions
11.7. Is inheritance really necessary
- The template method pattern is one of the few design patterns based on inheritance, but the JavaScript language doesn’t really provide true class inheritance, which is implemented through object-to-object delegation
11.8 summary
- The template method pattern is a typical design pattern that encapsulates changes to improve system scalability
- In traditional object-oriented languages, in a program that uses the template method pattern, the class of methods and execution order of the subclass are unchanged, so we abstract this logic into the template method of the parent class
- However, how the methods of subclasses are implemented is variable, so we encapsulate this part of the changing logic in the subclass. By adding new subclasses, we can add new functionality to the system without changing the abstract superclass and other subclasses, which is also open and closed
Chapter 12 Enjoy yuan mode
Writing in the front
- The Flyweight pattern is a pattern used for performance optimization
- The core of the share pattern is the use of sharing technology to effectively support a large number of fine-grained objects
- The share pattern is useful if the system is overloaded with memory due to the creation of a large number of similar objects
12.1. The mode of sharing elements for the first time
- Examples of 50 types of men’s underwear and 50 types of women’s underwear worn on plastic models for advertising photos
12.2. Internal state and external state
- The share pattern requires that the properties of an object be divided into internal and external states (states here usually refer to properties)
- The goal of the share pattern is to minimize the number of shared objects
- A few lessons on how to separate internal state from external state: internal state is stored inside objects; Internal state can be shared by several objects; The internal state is independent of the specific scenario and usually does not change; The external state depends on and changes according to the specific scenario. The external state cannot be shared.
- Enjoy yuan mode is a time for space optimization mode
- In general, the maximum number of objects in the system depends on the number of combinations of internal states
- How do you distinguish internal state from external state when using the key of the share pattern
- The attributes that can be shared by objects are usually divided into internal states. For example, no matter what style of clothes, they can be worn on the same male model or female model according to gender, and the gender of the model can be stored in the internal state of the shared object
- External states depend on and vary from scenario to scenario, just as in the example where each piece of clothing is different, they cannot be shared by some object and therefore can only be classified as external states
12.3. Common structure of share mode
12.4. File Uploading Example
- In the development of micro cloud upload module, the program performance has been improved with the help of the sharing mode
- 1. Object explosion: support to select 2000 files at the same time, each file corresponds to a JavaScript upload object creation; Supports several upload methods, such as browser plug-in, Flash and form upload, etc.
- 2. Upload files for reconstruction in Enjoy mode: Upload object must rely on uploadType attribute to work, this is because the actual working principle of plug-in upload, Flash upload and form upload is very different, and the interface they call is completely different. The type of plug-in must be made clear at the beginning of the creation of the object, so that the program can run. Have them call their respective start, Pause, Cancel, del, and so on
- 3. Stripping external state: After uploadType is identified as the internal state, the other external states are removed from the constructor and only the uploadType parameter is retained in the Upload constructor
- 4. The factory instantiates the object
- 5. The manager encapsulates external state
12.5. Practicality of enjoy yuan mode
- In general, the share mode can be used when
- 1. A large number of similar objects are used in a program
- 2. A large number of objects are used, resulting in a large memory overhead
- 3. Most of an object’s states can be changed to external states
- 4. After stripping out the external state of objects, you can replace a large number of objects with relatively few shared objects
12.6. Again, internal and external states
- There are as many shared objects in the system as there are combinations of internal states, while external states are stored outside the shared object and passed into the shared object as necessary to assemble a complete object
- 1. No internal state: The manager part of the code does not need to change, is still responsible for stripping and assembling the external state. As you can see, the factory that produces the shared object actually becomes a singleton factory when the object has no internal state
- 2. Enjoy without external state: The key to enjoy mode is to distinguish internal state from external state. The process of sharing is to strip out the external state, store it elsewhere, and then incorporate it into the shared object at the appropriate time
12.7. The object pool
- Object pool technology is widely used, HTTP connection pool and database connection pool are its representative applications
- 1. Object pool implementation
- 2. Universal object pool implementation
- Object pooling is another performance optimization that has some similarities to the metadata pattern, but does not separate internal state from external state
12.8 summary
- The share pattern is a pattern created to solve performance problems
- In a system with a large number of similar objects, the share mode can solve the performance problem caused by a large number of objects
Chapter 13 Responsibility chain model
- The chain of responsibility pattern is defined as avoiding coupling between the sender and receiver of the request by giving multiple objects the opportunity to process the request, connecting the objects into a chain, and passing the request along the chain until one object processes it
13.1. The chain of responsibility model in reality
- The example of handing coins on a bus
- The biggest advantage of the chain of responsibility pattern is that the request sender only needs to know the first node in the chain, thus weakening the strong connection between the sender and a set of receivers
13.2. Chain of responsibility pattern in actual development
- if.. The else combined if.. else
13.3. Refactor code with the Chain of Responsibility pattern
- Remove nested conditional branch statements and break them into smaller functions
13.5. Asynchronous chains of responsibility
- When you encounter asynchronous problems, such as making an Ajax asynchronous request in a node function, the result of the asynchronous request will determine whether to continue passRequest in the responsibility chain
- The asynchronous responsibility chain, coupled with the command pattern (which encapsulates Ajax requests as command objects), makes it easy to create an asynchronous Ajax queue library
13.6. Advantages and disadvantages of the chain of responsibility model
- The great advantage of the chain of responsibility pattern is that it decouples the complex relationship between the request sender and the N receivers. Since you don’t know which node in the chain can handle the request you send, you simply pass the request to the first node
- Secondly, after using the responsibility chain pattern, the node objects in the chain can be flexibly split and reassembled. Adding or removing a node, or changing the position of a node in a chain, is a snap
- Another advantage is that the starting node can be specified manually, and the request does not have to start at the first node in the chain
- One drawback is that there is no guarantee that a request will be processed by the nodes in the chain
- In addition, the responsibility chain mode makes the program have more node objects, most of the nodes may not play a substantial role in a request transfer process, their role is just to let the request to pass on, from the performance aspect, to avoid the performance loss caused by too long responsibility chain
13.7. Implement chains of responsibility with AOP
- There is a more convenient way to create chains of responsibility by taking advantage of the functional nature of JavaScript
- Antecedent Rewrite the function.prototype. after Function so that if the first Function returns’ nextsucceeded ‘, the request is passed on to the next Function
13.8. Get file upload objects in Responsibility chain mode
- We created an iterator to iterate over the appropriate file upload object, but using the chain of responsibility pattern can be simpler without creating the redundant iterator at all
13.9 summary
- The chain of responsibility pattern is one of the most overlooked patterns in JavaScript development
- The chain of responsibility pattern is a great way to manage code and reduce the coupling between the object that initiates the request and the object that processes it. The number and order of nodes in the responsibility chain can vary freely, and we can decide at run time which nodes to include in the chain
- Whether it’s a chain of scopes, a chain of archetypes, or an event bubble in a DOM node, we can find echoes of the chain of responsibilities pattern
- Chains of responsibility can also be combined with composition patterns to connect parts to their parents or to improve the efficiency of composition objects
Chapter 14 The Intermediary model
Writing in the front
- Object-oriented design encourages the distribution of behavior among objects and the partitioning of objects into smaller granularity, which helps increase the reusability of objects, but can in turn reduce their reusability as connections proliferate among these fine-grained objects
- The role of the mediator pattern is to decouple objects from each other
- By adding a mediator object, all related objects communicate through the mediator object rather than referring to each other, so when an object changes, the mediator object only needs to be notified. The mediator loosens the coupling between objects and can change their interactions independently. The mediator pattern turns the netted many-to-many relationship into a relatively simple one-to-many relationship
14.1. Real life intermediaries
- 1. Airport control tower
14.2. An example of mediator mode — Bubble House Games
- 1. Add teams to the game: when each player dies, the survival status of other teammates is traversed. If all teammates die, the game fails, and all players on the enemy team win
- 2. The problem with player growth: You can add players or teams to your game at will, but the problem is that each player is tightly coupled to the others
- 3. Transforming bubble Hall with intermediary mode: The playerDirector opens a receiveMessage interface that receives messages from the Player object. When the Player object sends a message, it always sends its this parameter to the playerDirector. So that the playerDirector can identify which player object the message came from; In addition to the broker itself, none of the players know the existence of any other player, the coupling relationship between the players and the players have been completely removed, a player of any operation need to notify the other players, not only need to send a message to the broker, mediator after processing the message object will reduce the processing result feedback to other players;
14.3. The intermediary example — buying goods
- 1. Start coding
- 2. Connections between objects
- 3. Possible difficulties
- 4. Bring in a mediator
14.4 summary
- The intermediary pattern is a kind of realization that caters to Demeter’s law. Demeter’s Law, also known as the least Knowledge principle, states that one subject should know as little as possible about another (similar to not talking to strangers)
- In the mediator mode, objects are barely aware of each other’s existence and can only influence each other through the mediator object
- The mediator pattern decouples objects, replacing the mesh many-to-many relationship between objects with a one-to-many relationship between the mediator and objects. Each object only needs to pay attention to the realization of its own function, and the interaction between objects is handed over to the intermediary object to realize and maintain
- The biggest disadvantage is the addition of a mediator object to the system, because the complexity of the interaction between objects is transferred to the complexity of the mediator object, making the mediator object often huge. The mediator object itself is often a difficult object to maintain
- In general, if the complex coupling between objects does make it difficult to call and maintain, and these couplings grow exponentially as the project changes, then we can consider refactoring the code with the intermediary pattern
Chapter 15 Decorator pattern
Writing in the front
- Many times in program development, you don’t want a class to be inherently large and have many responsibilities at once
- The decorator pattern can dynamically add additional responsibilities to an object without affecting other objects derived from that class
- Decorator pattern allows you to dynamically add responsibilities to objects during program execution without changing the objects themselves
15.1. Decorator patterns that mimic traditional object-oriented languages
- This way of dynamically adding responsibility to an object does not really change the object itself, but puts the object into another object, which is referred to in a chain, forming an aggregate object
15.2. The decorator is also the wrapper
- GoF originally wanted to call the decorator pattern the Wrapper pattern
- Functionally, the decorator describes the pattern well, but structurally, the Wrapper is more apt. The decorator pattern inserts an object into another object, essentially wrapping it around another object, forming a wrapper chain. The request is passed along the chain to all objects, and each object has an opportunity to process the request
15.3. Back to JavaScript Decorators
15.4. Decorator functions
- It’s easy to extend properties and methods on an object in JavaScript, but it’s hard to add extra functionality to a function without changing its source code. It’s hard to get into a function’s execution environment while the code is running
- Now we need a way to add functionality to a function without changing its source code, which is exactly what the open-close principle shows us
- One answer is to overwrite a function by saving the original reference
15.5. Decorate functions with AOP
- First Function is given. The prototype. Before method and the Function prototype. After methods
- Save the current this, which refers to the original function, and return a “proxy” function that is structured like a proxy and does not take on the responsibilities of a proxy (controlling access to objects, etc.). Its job is to forward requests to the newly added function and the original function separately, and it is responsible for ensuring their execution order, so that the newly added function runs before the original function (predecoration), thus achieving the effect of dynamic decoration
- Function. The prototype. After. The principle and the Function of the prototype. Is the same as before, the only difference is that let the newly added functions in Function executed later
15.6. Application examples of AOP
- Whether written in business code or at the framework level, we can divide behavior into more granular functions by responsibility and then combine them together through decoration, which helps us to write a loosely-coupled and highly reusable system
- 1. Data statistics reporting: Separating business code from data statistics code is one of the classic uses of AOP in any language
- 2. Use AOP to dynamically change function parameters: One of the simplest solutions to CSRF attacks is to add a Token parameter to the HTTP request
- 3. Plug-in form validation: Separate the validation input from the Ajax request submission code, put the validation input logic into validata, and specify that validata returns false to indicate validation failure
- This decoration superimposes the scope of the function, and performance may suffer if the decoration chain is too long
15.7. Decorator pattern and proxy pattern
- Both patterns describe how to provide a degree of indirect reference to an object, and their implementation parts retain a reference to another object and send requests to that object
- The purpose of the proxy pattern is to provide a substitute for an ontology when direct access to that ontology is inconvenient or undesirable. The ontology defines key functionality, and the proxy provides or denies access to it, or does additional things before accessing the ontology
- The purpose of decorator pattern is to dynamically add behavior to an object
- The proxy pattern usually has only one layer of proxy-ontology references, whereas the decorator pattern often forms a long decorative chain
Chapter 16 State Mode
- The key of state mode is to distinguish the state inside the transaction. The change of state inside the transaction often brings about the behavior change of things
16.1. Initial recognition of state patterns
- Example of an electric light switch
- When we talk about encapsulation, we tend to encapsulate the behavior of an object first, not its state. In state mode, however, the opposite is true. The key of state mode is to encapsulate each state of things into a separate class, and the behavior related to this state is encapsulated within this class
- The benefits of using a state pattern are obvious: it localizes the relationship between a state and its corresponding behaviors, which are dispersed and encapsulated in their corresponding state classes for easy reading and management of code
- In addition, switching between states is distributed within the state class, which eliminates the need to write a lot of if and else conditional branching languages to control switching between states
16.2. Definition of state mode
- The GoF definition of a state pattern allows an object to change its behavior when its internal state changes, as if the object modifies its class
- The first part means encapsulating the state into separate classes and delegating requests to the current state object, with different behavior changes as the internal state of the object changes
- The second part is that from the customer’s point of view, we use objects that behave very differently in different states. This object appears to be instantiated from different classes, but in fact it uses the effect of delegation
16.4. Lack of workarounds for abstract classes
- In Java, all State must be inherited from a State abstract superclass, although there is an option to implement the State interface if no common functionality is worth putting into the abstract superclass
16.5. Another example of a state pattern — file upload
- File uploading program has scan, upload, pause, upload success, upload failed these states, music player can be divided into loading, playing, pause, play finished these states
- 1. More complex switching conditions
- 2. Some preparation
- 3. Start coding
- 4. Upload the status mode reconstruction file
16.6. Pros and cons of state patterns
- The advantages of the state pattern are as follows: 1. The state pattern defines the relationship between state and behavior, and encapsulates them in a class. It is easy to add new states and transitions by adding new state classes; 2, avoid infinite expansion of Context, state switching logic is distributed in the state class, also remove the Context originally too many conditional branches; 3. Use objects instead of strings to record the current state, making the state switch more obvious; 4. The request action in Context and the behavior encapsulated in the state class can easily change independently of each other;
- Disadvantages of state mode: 1, many state classes will be defined in the system, writing 20 state classes is a boring work, and many objects will be added to the system; 2. The logic is scattered in the state class, which avoids undesirable conditional branching statements, but also causes the problem of logic dispersion. We cannot see the logic of the whole state machine in one place.
16.7. Performance optimization points in state mode
- Some big optimizations: There are two options for managing the creation and destruction of state objects. The first is to create state objects only when they are needed and then destroy them. The second is to create all state objects from the start and never destroy them. A set of state objects is created for each Context object. In fact, these state objects can be shared. Each Context object can share a state object.
16.8. Relationship between state mode and policy mode
- The state pattern and the policy pattern are twins, both encapsulating a set of algorithms or behaviors whose class diagrams look almost identical but differ greatly in intent
- Policy patterns and state patterns are similar in that they both have a context, policies or state classes to which the context delegates requests
- The difference between them is that each policy class in the strategy mode is equal and parallel, without any connection between them. Therefore, customers must be familiar with the role of these policy classes, so that customers can actively switch algorithms at any time. However, in the state mode, the state and the behavior corresponding to the state have long been encapsulated, and the switch between the states has long been specified, and the “behavior change” happens within the state mode
16.9.JavaScript version of the state machine
- A state pattern is one of the implementations of a state machine, but in a “classless” language like JavaScript, there is no requirement that a state object be created from a class. Another point is that JavaScript makes it very easy to use delegate techniques without having to make one object hold another
16.10. Table-driven finite state machines
- Another way to implement state machines, the core is based on table driven. It is clear from the table that the next state is determined by both the current state and the behavior. This way, we can look up states in the table without having to define many conditional branches
16.11. Other state machines in real projects
- In the actual development, many scenes can be simulated by the state machine, such as a drop down menu in hover action under the display, suspension, hide and other states; A TCP request can be established, monitored, or closed. A fighting game has characters that attack, defend, jump, fall, and so on
16.12 summary
- The state model is probably one of the most underrated
- In fact, after refactoring the code through state patterns, much of the messy code becomes clear
Chapter 17 Adapter Patterns
Writing in the front
- The role of the adapter pattern is to solve the problem of interface incompatibilities between two software entities
- There are many scenarios in program development where we try to call an interface of a module or object, only to find that the format of the interface does not meet current requirements
- There are two solutions. The first is to modify the original interface implementation, or the second is to create an adapter that converts the original interface into another interface that the customer wants, and the customer only needs to deal with the adapter
17.1. Adapters in the real world
- Several adapter modes in real life: 1. Port type plug converter; 2. Power adapter; 3. Turn the USB interface
17.2. Application of the adapter pattern
- The adapter pattern is a “never too late” pattern that no one will use at the beginning of a program’s design
17.3 summary
- The adapter pattern is a relatively simple one
- Some patterns are very similar in structure to the adapter pattern, such as the decorator pattern, the proxy pattern, and the facade pattern
- The adapter pattern is primarily used to solve the problem of mismatches between two existing interfaces, regardless of how those interfaces were implemented or how they might evolve in the future
- Decorator mode and proxy mode also do not change the interface of the original object, but the purpose of decorator mode is to add functionality to the object
- The facade pattern is similar to the adapter pattern in that some people think of the facade pattern as an adapter for a set of objects, but the most notable feature of the facade pattern is that it defines a new interface
Chapter 18 Principle of Single responsibility
- These design principles summarized by the predecessors usually refer to the single responsibility principle, Richter substitution principle, dependency inversion principle, interface isolation principle, composite reuse principle and least knowledge principle
Writing in the front
- The responsibility of the Single Responsibility Principle (SRP) is defined as “cause of change”
- The SRP principle is that an object (method) does only one thing
18.1. SRP principles in design patterns
- The SRP principle is widely used in many design patterns, such as the proxy pattern, the iterator pattern, the singleton pattern, and the decorator pattern
18.2. When should responsibilities be separated
- The SRP principle is one of the simplest and most difficult principles to apply correctly
- On the one hand, if two responsibilities always change at the same time as requirements change, there is no need to separate them
- Axes of change in responsibilities, on the other hand, are meaningful only if they are certain to change
18.4. Advantages and disadvantages of the SRP principle
- The SRP principle has the advantage of reducing the complexity of individual classes or objects and breaking them down into smaller granularity by responsibility, which facilitates code reuse and unit testing
- The SRP principle has some disadvantages, most notably the increased complexity of writing code
Chapter 19 The least Knowledge principle
- The least knowledge principle (LKP) states that a software entity should interact with as few other entities as possible.
- The software entity here is a broad concept, including not only objects, but also systems, classes, modules, functions, variables, etc
19.1. Reduce connections between objects
- The least knowledge principle requires that we design programs with minimal interaction between objects
19.2. Least knowledge principle in design patterns
- The least knowledge principle is most commonly reflected in design patterns in the mediator pattern and appearance pattern
- 1. The mediator pattern (by adding a mediator object, all related objects communicate through the mediator object instead of referring to each other)
- 2. Appearance pattern (Appearance pattern serves to shield the customer from the complexity of a set of subsystems. The facade mode provides a simple and easy to use high-level interface to the customer, the high-level interface will forward the customer request to the subsystem to complete the specific function realization; Facade patterns serve two main purposes (providing a simple and convenient entry point for a set of subsystems; Isolate the customer from the complex subsystem without the customer having to understand the details of the subsystem))
19.3. Embodiment of encapsulation in the principle of least knowledge
- Encapsulation is largely about hiding data. A module or object can hide its internal data or implementation details, exposing only the necessary interface apis for external access
- The least knowledge principle is also known as the Law of Demeter (LoD)
Chapter 20 Openness – Closure principle
Writing in the front
- The open – closed principle (OCP) is the most important principle in object – oriented programming
- The open-closed principle is defined as follows: Software entities (classes, modules, functions), etc., should be extensible but not modifiable
20.1. Extend window.onload
- Add new functionality to the window.onload function by adding code, not modifying it
- By decorating the function dynamically, we completely ignore the internal implementation of the previous window.onload function, whether it was elegant or ugly
20.2. Open and closed
- Introduces the idea of the open-closed principle – when it is necessary to change the functionality of a program or to add new features to the program, you can use the method of adding code without changing the source code of the program
20.3. Eliminate conditional branches by object polymorphism
- Using the idea of polymorphism, we isolate the invariant parts of the program (animals all bark) and encapsulate the variable parts (different types of animals make different noises), thus making the program scalable
20.4. Identify changes
- We can still find some rules for keeping programs as open and closed as possible. The most obvious is to find out where changes are going to happen in the program and then encapsulate those changes
- By encapsulating change, you can isolate the stable parts of the system from the easily changing parts
- In addition to taking advantage of object polymorphism, there are other ways to help us write code that follows the open-closed principle: 1. Place the hook; 2. Use callback functions
20.5. Open-closed principle in design patterns
- Almost all design patterns adhere to the open-closed principle, and the good designs we see often survive the open-closed principle
20.6. Relativity of the open-closure principle
- In fact, it’s not easy to keep a program completely closed
- And the price of conforming to the open-closed principle is the introduction of more levels of abstraction, which can increase code complexity
Chapter 21 Interface and Interface – oriented Programming
Interfaces are often referred to in the following senses
- By communicating through actively exposed interfaces, details of the workings of a software system can be hidden. This is the first interface meaning we are most familiar with
- The second type of interface is the keyword provided by some languages, such as Java’s Interface. The interface keyword can produce a completely abstract class
- The third type of interface is the one we talk about in “interface oriented programming”, where the meaning of interface is more abstract
21.1. Back to Java’s abstract classes
- Statically typed languages are often designed to be “upward-transitioned”. When assigning a value to a class variable, the type of the variable can use either the class itself or a superclass of the class
- Programmatically, “programming for interfaces” is really “programming for supertypes”
21.2. Interface
- Although many people make a conscious distinction between abstract classes and interfaces in practice, using interfaces is actually a form of inheritance, called interface inheritance
21.3. Does the JavaScript language require abstract classes and interfaces
- Abstract classes and interfaces are mainly used in the following two aspects: (1) To hide the real type of the object through upward transformation, so as to show the polymorphism of the object; 2. Some contract behaviors between contract classes)
- Very few people in JavaScript development care about the real type of an object
- Because no upward transition is required, the interface’s greatest role in JavaScript is reduced to checking the code’s standardization
21.4. Check the interface by duck type
- Duck type is an important concept in dynamic language object-oriented design. Using the duck type idea, you can easily implement the design principle mentioned in this chapter in dynamically typed languages without the aid of supertypes: programming for interfaces, not for implementations
Writing interface based command patterns in TypeScript
- Typescript is a programming language developed by Microsoft that is a superset of JavaScript. Typescript code is eventually compiled and executed as native JavaScript code. With Typescript, we can write JavaScript programs in a static language
Chapter 22 Code Refactoring
- There is an inherent relationship between patterns and refactoring. From a certain point of view, the purpose of a design pattern is to provide goals even for many refactoring activities
22.1. Refining functions
- This is a very common optimization, and the main benefits of doing so are as follows: 1. 2. Separate functions facilitate code reuse; 3. Independent functions are easier to overwrite; 4. Independent functions with good names act as annotations themselves;
22.2. Merge repeated conditional fragments
- Conditional branch statements have some duplicate code scattered within them, so merge de-duplication is necessary
22.3. Distill conditional branch statements into functions
- Complex conditional branching statements make programs difficult to read and understand, and can easily lead to a large function
22.4. Use cycles wisely
- The right use of loops not only does the same thing, but it also leads to less code
22.5. Let the function exit early instead of nested conditional branches
- There are some different opinions about “a function has only one exit”
- A common trick is to reverse the outer if expression when faced with a nested if branch
22.6. Pass object arguments instead of long argument lists
- Sometimes a function may take more than one argument, and the more arguments there are, the harder the function is to understand and use
22.7 Minimize the number of parameters
- In real development, passing parameters to a function is inevitable, but we should minimize the number of parameters the function receives
22.8. Use less ternary operators
- It’s hard to argue that ternary operators are high performance and low code
- The amount of code saved by ternary operators is also negligible compared to the loss of code readability and maintainability
Write in the back
- PDF books, notes a mind map, along with the book code package download address: pan.baidu.com/s/17QLgFO2z… (Extraction code: J29J)
- Purchase address: u.jd.com/wlo6gr (it is recommended to buy paper books to study)