In the process of writing JS and assembling code, using certain design patterns can make our code more elegant and flexible.
Next, I will give you a brief introduction to the use of design patterns in these libraries, grammars and frameworks by combining subscribe with redux, class in ES6, $dispatch in vue, and on/off in jquery.
Problems solved by design patterns
Design patterns are not very mysterious knowledge. Many students have inadvertently used a lot of design patterns when writing JS code. .
The author believes that abstracting design patterns to discuss them separately is just like abstracting bubbles and sorting from algorithms, in order to describe a commonly used JS pattern.
By studying this type of pattern, let the pattern guide our code structure and JS algorithm.
Overview of some commonly used design patterns
observer [Observer pattern]
Actively trigger the callback behavior of the observer queue and hashMap according to changes in status
A simple observer pattern code practice
class StateTracker{ constructor(){ this.observers = []; this.internamState= 10; } // 改变内部状态,触发状态的观察者列表 change(val){ this.internamState= val; this.observers.forEach(observer=>observer(val)); } registerObserver(ObserverFn){ this.obserers.push(ObserverFn) } }
publish/subscribe [Subscription publishing mode]
Store the topic/callback form of hashMap in the shared access space of the code module.
Add on/off/trigger and other interfaces to implement actions such as mounting, removal, and triggering.
A simple subscription-publishing model code practice
class PubSubHandler{ constructor(){ this.eventPool = {}; } //移除 off(topicName){ delete this.observers[topicName] } //发布 trigger(topicName,...args){ this.eventPool[topicName] && this.eventPool[topicName].forEach(callback=>callback(...args)); } //订阅 on(topicName,callback){ let topic = this.eventPool[topicName] ; if(!topic){ this.eventPool[topicName] =[] } this.eventPool[topicName].push(callback) } }
singleton[single case mode]
There is only one instance of the constructor, and the internal instance is usually stored through a closure. Interface access to internal instances.
var singleton = ()=>{ var instance; var createInstance = ()=>{ this.a = 1; this.b = 2; } return { getInstance:()=>{ if(!instance){ instance = createInstance(); } return instance; } } } var test = singleton(); test.getInstance() == test.getInstance() //true
decorator mixed mode
This mode is to decorate more behaviors on the original object and keep the variable name unchanged. If you have used ES7's @decorator or python and other languages, you should be familiar with decorator.
function decorator(sourceObj,decortorFn){ decortorFn(sourceObj); return sourceObj } var d = {a:1}; // d变为了{a:1,b:1} d = decorator(d,(d)=>{d.b=1});
mixin blending mode
This mode is somewhat similar to decorator, except that its function is more vertical. It is the act of adding and overwriting objects on top of the original objects. Compared with methods such as extends and Object.assign, the mixin mode is more expressive. The mixin pattern cannot be generalized. There may be different mixin strategies based on different data types, such as vue.mixin
class StateTracker{ constructor(){ this.raw = { a:1, b:2 } } mixin(obj){ Object.assign(this.raw,obj) } }
. The author will introduce so many design patterns for the time being. The following will focus on commonly used frameworks, grammars, libraries, etc. Explain the application of these design patterns.
The use of observer mode in redux
var store = createStore(reducer,initialState);//注册redux store,存储在 nextListeners数组 var test = store.subscribe(()=>{console.log('我注册了!')});// 取消注册监听 test.unsubscribe(); publish/subscribe在jquery中的使用 $(document).on('hello',()=>{console.log('hello')})$(document).trigger('hello');$(document).off('hello')
The practice of decorator mode in react-redux
//装饰器 @connect(state=>state) class Container extends Component{ render(){ return JSON.stringify(this.props) } }