目录

前言

创建型模式

单例模式

构造器+原型

简单工厂模式

工厂模式

创建型模式比较

结构性模式

模块模式

外观模式

混入模式

装饰模式

适配模式

行为型模式

观察者模式

中介者模式

命令模式

责任链模式

设计原则

单一职责原则

最少知识原则

开放-封闭原则

  • 前言

  为什么要学习设计模式?

  解耦合、解决复用、提高观察高度

  • 创建型模式

  1、单例模式

  场景:点击页面一个按钮,弹出遮罩层。

  遇到这个问题,首先我们想到用一个方法创建一个div,然后append到body上,实现点击事件,代码如下:

  1. function createTip(){
  2. var div = document.createElement("div");
  3. return document.body.appendChild(div);
  4. }
  5. $('#user').click( function(){
  6. var tip = createTip();
  7. $(tip).show();
  8. });

  虽然功能实现了,但是这种方法有一个大问题:反复创建Dom!

  所以我们需要对它进行改造,改造完成之后,代码如下:

  1. var tipEl = document.createElement("div");
  2. tipEl.style.display = "none";
  3. document.body.appendChild(tipEl);
  4. function showTip(){
  5. tipEl.style.display = "";
  6. }
  7. $('#user').click( function(){
  8. showTip();
  9. });

  虽然避免了上面方法重复创建dom的缺点,但是这么实现还是有很大的弊端:1、暴露全局变量tipEl,尤其是在做组件化开发的时候要尽可能不要暴露全局变量,否则容易引起全局变量污染和冲突;2、创建完成之后用户可能不去点击,导致dom浪费。

  再一次升级,代码如下:

  1. var createTip = function(){
  2. var tip;
  3. return function(){
  4. return tip ||
  5. (tip=document.body.appendChild(document.createElement("div")))
  6. }
  7. }();
  8. $('#user').click( function(){
  9. var tip = createTip();
  10. $(tip).show();
  11. });

  好,这就是最终的单例模式实现了。

  为什么createTip要return一个function,而不是直接把tip||(tip=document.body.appendChild(document.createElement("div"))) 返回出来呢?

  因为这样可以做到惰性加载,只在需要的时候创建(这也是在click方法中var tip = createTip();要加上()的原因),否则浏览器遇到createTip的定义的时候就直接执行返回tip,这不是我们所希望的。

  总结:

  a、唯一实例:节约系统资源,提高性能;

  b、命名空间:减少全局变量的数量;

  c、实例控制:私有实例,提供访问接口

  d、适用场景:一个类只有一个实例,提供全局访问接口;资源共享的情况下,避免性能或其他损耗,如计数器、配置;资源控制的情况下,方便资源之间的互相通信,如线程池。

  2、构造器+原型

  场景:酒店有多种类型的房间,如何描述各种房间之间的关系。

  想到第一种,函数方法,代码如下:

  1. function Room(roomNumber, type, money) {
  2. this.roomNumber = roomNumber;
  3. this.type = type; this.money = money;
  4. this.getInfo = function() {
  5. return this.roomNumber + ', ' + this.type + ', ' + this.money;
  6. };
  7. }
  8. var roomA = Room('101', '标间', 200);
  9. console.log(roomA);//如何获取房间信息呢???

  如何获取房间信息成为一大问题,像第8行代码那样直接调用Room方法,其实this指向的是window对象,故Room方法内部的属性和方法赋值都是赋值给了window对象,所以即使可以通过window.getInfo()来调用,但是显得毫无意义。

  于是,我们想到了构造器的实现方法,代码如下:

  1. function Room(roomNumber, type, money) {
  2. this.roomNumber = roomNumber;
  3. this.type = type;
  4. this.money = money;
  5. this.getInfo = function() {
  6. return this.roomNumber + ', ' + this.type + ', ' + this.money;
  7. };
  8. }
  9. var roomA = new Room('101', '标间', 200);
  10. console.log(roomA.getInfo());//101,标间,200
  11. var roomB = new Room('102', '海景房', 799);
  12. console.log(roomB.getInfo());//102,海景房,799

  每次调用使用new关键字实例化对象,然后调用getInfo方法。

  够简单、够直观,但是又有新问题,getInfo每次实例化都要重新创建,消耗内存。

  开启外部添加原型模式,代码如下:

  1. function Room(roomNumber, type, money) {
  2. this.roomNumber = roomNumber;
  3. this.type = type;
  4. this.money = money;
  5. }
  6. Room.prototype.getInfo = function() {
  7. return this.roomNumber + ', ' + this.type + ', ' + this.money;
  8. }
  9. var roomA = new Room('101', '标间',200);
  10. console.log(roomA.getInfo());//101,标间,200
  11. Room.prototype.book = function() {
  12. console.log("book success");
  13. }
  14. roomA.book();//book success

  优点:方法共享,节约内存;随时添加方法且可以被实例化使用;

  缺点:方法零散,不利于管理。

  那就把原型统一起来,代码如下:

  1. function Room(roomNumber, type, money) {
  2. this.roomNumber = roomNumber;
  3. this.type = type;
  4. this.money = money;
  5. }
  6. Room.prototype = {
  7. constructor : Room,//这行代码很重要,因为已经重新定义了prototype的“指针”,如果不自己指定的话默认就是object,而不是Room
  8. getInfo : function() {
  9. return this.roomNumber + ', ' + this.type + ', ' +this.money
  10. }
  11. }
  12. var roomA = new Room('101', '标间', 200);
  13. console.log(roomA.getInfo());//101,标间,200
  14. console.log(roomA.constructor == Room);//true
  15. console.log(roomA instanceof Room);//true

  其中,所有的方法和变量都会暴露出来,这显然不够合理,更加优化的方式是把Room.prototype设计成揭示型的原型,利用自执行函数可以有效地保护私有变量和方法,只暴露自己想暴露的东西,代码如下:

  1. Room.prototype = function(){
  2. var getInfo = function(){
  3. return this.roomNumber + ', ' + this.type + ', ' + this.money;
  4. }
  5. return {
  6. constructor:Room,
  7. getInfo : getInfo
  8. }
  9. }()

  总结:

  a、适用场景:一个类有多个实例,且相互独立,如UI组件。

  3、简单工厂模式

  场景:某旅游网站有机票预订和酒店预订功能,如何实现它们的关系。

  场景实现,代码如下:

  1. var PRODUCT_TYPE = {
  2. AIR_TICKET : "01",
  3. HOTEL : "02"
  4. }
  5. function User(){
  6. this.shopCart = [];
  7. }
  8. User.prototype = {
  9. constructor : User,
  10. order : function(productType){
  11. var product = null;
  12. switch(productType){
  13. case PRODUCT_TYPE.AIR_TICKET:
  14. product = new Flight();
  15. case PRODUCT_TYPE.HOTEL:
  16. product = new Hotel();
  17. default:
  18. }
  19. this.shopCart.push(product);
  20. }
  21. }

  此时如果想增加火车票业务,删除机票业务,该怎么实现?需要改动的代码一点都不灵活,这时就需要我们理清用户和具体业务之间的关系,用户仅仅只和订单有关系。

  使用简单工厂模式,代码如下:

  1. var productFactory = (function(){
  2. var productFoctories = {
  3. "airTicket" : function(){
  4. return new AirTicket();
  5. },
  6. "hotel" : function(){
  7. return new Hotel();
  8. }
  9. }
  10. return {
  11. create : function(productType){
  12. return productFoctories[productType];
  13. }
  14. }
  15. })();
  16. User.prototype = {
  17. constructor : User,
  18. order : function(productType){
  19. var product = productFactory.create(productType);
  20. this.shopCart.push(product);
  21. }
  22. }

  总结:

  对象的创建和使用分离,使用一个类生成实例。

  a、使用类User:使用类仅使用产品,职责单一;

  b、工厂类Factory:对象类的集中管理;

  c、对象类Hotel:易于扩展,仅影响工厂类;

  d、适用场景:根据不同参数产生不同实例,这些实例有些共性的场景,使用者只需使用产品,无需关注产品的创建细节。

  

  4、工厂模式

  场景:某旅游网站有很多种酒店,不同的酒店内也有很多种房间,如何清楚地描述它们之间的关系。

  工厂实现,代码如下:

  1. /*********RoomBase ***********/
  2. var RoomBase = function(){};
  3. RoomBase.prototype = {
  4. constructor : RoomBase,
  5. create : function(){
  6. throw new Error("room create not impl!");
  7. },
  8. book : function(){
  9. this.state = "1";
  10. },
  11. hasWindow : function(){
  12. return true;
  13. }
  14. }
  15. /********************/
  16. var RoomA = function(){};
  17. extend(RoomA, RoomBase);//继承
  18. RoomA.prototype.create = function(type){
  19. console.log("这是标间");
  20. }
  21. RoomA.prototype.hasWindow = function(){
  22. return false;
  23. }
  24. var RoomB = function(){};
  25. extend(RoomB, RoomBase);
  26. RoomB.prototype.create = function(type){
  27. console.log("这是大床房");
  28. }
  29. /*********HotelBase ***********/
  30. var HotelBase = function(){
  31. this.roomFoctory = {};
  32. };
  33. HotelBase.prototype = {
  34. constructor : HotelBase,
  35. getRoom : function(type){
  36. return this.roomFactory[type];
  37. },
  38. bookRoom : function(type){
  39. var room = this.getRoom(type);
  40. room.book();//预订
  41. }
  42. }
  43. var HotelA = function(){
  44. this.roomFoctory = {
  45. "RoomA" : function(){
  46. return new RoomA();
  47. },
  48. "RoomB" : function(){
  49. return new RoomB();
  50. }
  51. }
  52. };
  53. extend(HotelA, HotelBase);
  54. var HotelB = function(){
  55. this.roomFoctory = {
  56. "RoomA" : function(){
  57. return new RoomA();
  58. },
  59. "RoomC" : function(){
  60. return new RoomC();
  61. }
  62. }
  63. };
  64. extend(HotelA, HotelBase);

  针对该旅游网站,网站管理酒店,酒店管理房间,网站不能直接管理房间,所有房间预订的功能全部走酒店的接口,跟网站没有关系,条理才比较清晰。

  总结:

  a、对象的创建和使用分离,子类决定成员变量的具体类;

  b、使用类HotelBase:提供对象类的管理;

  c、创建类HotelA:管理对象的实例化,多态;

  d、对象类Room:职责单一,扩展仅影响相关创建类;

  e、根据不同场景产生不同实例,这些实例有些共性的场景,使用者需要明确产品使用的场景,无需关心产品创建细节。

  5、创建型模式比较

  工厂模式:

    ①可创建多个相似对象;

    ②屏蔽了子对象类型(如上例中,使用Hotel预订的时候我们不知道它是A酒店还是B酒店,预订的时候是调用了HotelBase的基类中的book实现,根本没有关心它是酒店A还是酒店B)。

  构造函数模式:

    ①可创建多个相似对象;

    ②可识别子对象类型;

    ③创建多个完成相同任务的实例。

  原型模式:

    ①可创建多个相似对象;

    ②可识别子对象类型;

    ③多个实例共享公共方法。

  

  • 结构型模式

  1、模块模式

  1. var productFactory = (function(){
  2. var productFoctories = {
  3. "airTicket" : function(){
  4. return new AirTicket();
  5. },
  6. "hotel" : function(){
  7. return new Hotel();
  8. }
  9. }
  10. return {
  11. create : function(productType){
  12. return productFoctories[productType];
  13. }
  14. }
  15. })();

  总结:

  a、模块模式就是我们常说的命名空间,里面的东西根本不重要;

  b、保护私有接口,开放公共接口;

  c、模块化是面向对象的第一步;

  d、遵循单一职责原则。

  2、外观模式

  1. /****例1*****/
  2. var product;
  3. function getProduct(){
  4. if(!product){
  5. product = productFactory.create();
  6. }
  7. return product;
  8. }
  9. /****例2*****/
  10. /** * 同时阻止事件默认行为和冒泡 * @param e */
  11. var stopEvent = function(e){
  12. e.stopPropagation();
  13. e.preventDefault();
  14. }

  对相关的操作进行一层包装,比如例2中需要我们每次阻止事件冒泡的时候打一个日志console.log('日志'),那我们只需要在stopEvent的方法中写就行了,而不需要在每个需要阻止事件冒泡的地方去打日志。

  总结:

  a、更高层次的接口抽象,隐藏底层的真实复杂性;

  b、遵循最少知识原则。(你只需要知道有一个接口可以实现你的需求,而你不需要知道接口中到底调用了哪些方法去实现你的需求)

  3、混入模式

  场景:一个房子可以用来出租或出售,在不同的场景下有不同的功能,比如出售还涉及到房产证等等其他的一系列东西,所以单单通过一个属性是办不到的,这个时候就需要使用混入模式。代码如下:

  1. /******基础对象********/
  2. var Room = function(){};
  3. Room.prototype = {
  4. constructor:Room,
  5. create:function(){
  6. console.log('create');
  7. },
  8. book:function(){
  9. console.log('book');
  10. }
  11. };
  12. /******混入对象********/
  13. var Goods = function(){};
  14. Goods.prototype = {
  15. sell:function(){
  16. console.log('sell');
  17. }
  18. };
  19. /******混入方法********/
  20. var mixin = function (receiver, mixinObj) {
  21. // 如果存在三个以上的参数的话,从第三个开始表示要混入的方法名
  22. if (arguments[2]) {
  23. for (var i = 2, len = arguments.length; i < len; i++) {
  24. receiver.prototype[arguments[i]] = mixinObj.prototype[arguments[i]];
  25. }
  26. }
  27. // 否则混入全部方法
  28. else{
  29. for(var methodName in mixinObj.prototype){
  30. // 防止混入覆盖
  31. if(!receiver.prototype[methodName]){
  32. receiver.prototype[methodName] = mixinObj.prototype[methodName];
  33. }
  34. }
  35. }
  36. }
  37.  
  38. /******混入操作********/
  39. mixin(Room,Goods);
  40. var roomA = new Room();
  41. roomA.sell();//调用混入后的方法

  “房屋类”混入“商品类”的出售属性,房屋就具有了出售的功能,同理,如果混入了出租的属性,就具备了出租的功能。

  总结:

  a、通过函数复用达到对象扩充的目的;

  b、混入和继承的区别:混入只完成了方法的转移,两个对象还是两个对象,毫无任何关系;

  c、混入和组合的区别:组合是拥有的关系,比如酒店拥有房间,酒店可以操作房间,但是房间的属性还是房间的,不属于酒店。

 

  4、装饰模式

  场景:一个酒店的房间有淡季价格和旺季价格之分,如何实现。

  1. var Room = function(price){
  2. this.price = price;
  3. };
  4. Room.prototype = {
  5. constructor:Room,
  6. getPrice:function(){
  7. return this.price;
  8. }
  9. };
  10. var LowSeasonRoom = function(room){
  11. this.room = room;//注入Room,Room和LowSeasonRoom是组合的关系
  12. };
  13. LowSeasonRoom.prototype.getPrice = function(){
  14. return this.room.getPrice()*0.9;
  15. };
  16. var HighSeasonRoom = function(room){
  17. this.room = room;
  18. };
  19. HighSeasonRoom.prototype.getPrice = function(){
  20. return this.room.getPrice()*1.2;
  21. };
  22. /****************使用*****************/
  23. var roomA = new LowSeasonRoom(new Room(200));
  24. console.log(roomA.getPrice());//

  总结:

  a、动态改变对象实现对象扩充;(比如密码输入框是文本输入框的装饰模式,从文本输入框中单独剥离出来单独实现密码输入框的业务需求)

  b、缺点是增加了架构的复杂度。

  5、适配模式

  总结:

  a、主要用来解决对象之间的不兼容性;

  b、sum函数:可以不只是两个数的sum,可以通过arguments适配多个参数的sum;

  c、jQuery版本升级:比如版本升级之后废弃了某个方法一定是有其他的方法来兼容;

  d、apply函数:指定作用域随时都可以调用。

  • 行为型模式

  1、观察者模式

  场景:酒店的某个房间需要客房服务,酒店如何响应。

  1. var Room = function(){};
  2. Room.prototype = {
  3. constructor : Room,
  4. service : function(){
  5. this.fire("service", this.roomId);
  6. }
  7. }
  8. var Hotel = function(){};
  9. Hotel.prototype.addRoom = function(room){
  10. room.on("service", function(){
  11. //TODO 服务
  12. });
  13. }

  总结:

  a、命令的发起者和执行者解耦合,don't call us,we will call you;

  b、一个发起者可能对应多个执行者;

  c、一个执行者也可能是其他执行者的命令发起者

  d、常用的场景:比如我们页面中经常会用到iframe,一个子页面需要调用父页面的方法,经常会使用parent.functionNmae()去调用,但是一旦取不到父页面,这里就会报错,所以正确的处理方式是在父页面监听事件,在子页面触发事件,这样就算服务不到也不会报错,通常在父子页面中都存在的是body,固我们习惯性把事件的监听和触发放到body上执行。

  2、中介者模式

  场景:一个酒店某个房间需要服务,酒店中有多个服务员,这时候该怎么实现呢。

  这个时候就不能用观察者模式,因为观察者模式是不确定谁来服务的,万一酒店中所有的服务员都来服务怎么办,得由酒店来确定到底哪个服务员过来提供服务。

  1. var Room = function(){};
  2. Room.prototype = {
  3. constructor : Room,
  4. service : function(){
  5. this.fire("service", this.roomId, type);
  6. }
  7. }
  8. var Waiter = function(){};
  9. Waiter.prototype = {
  10. constructor : Waiter,
  11. service : function(){
  12. //TODO 服务
  13. }
  14. }
  15. var Hotel = function(){};
  16. Hotel.prototype.addRoom = function(room){
  17. room.on("service", function(roomId, type){
  18. if(type == "设备修理"){
  19. waiterA.service();
  20. }else{
  21. if(roomId.startWith("3")){
  22. waiterB.service();
  23. }else{
  24. waiterC.service();
  25. }
  26. }
  27. });
  28. }

  总结:

  a、管理复杂对象关系:把多对多拆分成多对一;

  b、对象间的耦合转移至中介者;

  c、中介者的稳定性至关重要。

  3、命令模式

  场景:如果酒店提供的服务有多种多样,该如何实现。

  此时就需要用到命令模式,代码如下:

  1. var Services = {
  2. clean : function(){
  3. console.log("打扫卫生");
  4. },
  5. consult : function(){
  6. console.log("咨询");
  7. }
  8. }
  9. var ServcieCommand = function(){
  10. return {
  11. execute : function(receiver, command){
  12. receiver[command]();
  13. }
  14. }
  15. }();

  总结:

  a、命令的发起和实现解耦合

  4、责任链模式

  场景:假设某个酒店发生了斗殴,如果酒店内部可以处理则自己处理,否则就让警察处理,责任一层层转移。

  1. var Hotel = function(){
  2. this.on("fight", function(){
  3. if(this.canDo()){//内部处理
  4. this.do();
  5. }else{//报警
  6. Police.do();
  7. }
  8. });
  9. };
  10. Police = function(){
  11. return {
  12. do : function(){
  13. if(this.canDo()){
  14. console.log("over");
  15. }else{
  16. //TODO 转上级处理。。。
  17. }
  18. }
  19. }
  20. }();

  总结:

  a、每个节点只知道下线,不知道最终执行者;

  b、可能出现无人处理的情况;

  c、缺点调试困难(所以需要我们在每个执行环节打日志)。

  • 设计原则

  1、单一职责原则

  如何确定一个职责or两个职责:

  a、职责被定义为“引起变化的原因”;

  b、若两个职责总是同时变化,则可以作为一个职责;(比如请求数据之后渲染图表)

  c、发生变化才对职责的限定有意义,不变没有必要分离

  违反不一定是坏事:

  比如:$.attr()这个方法有赋值也有取值的职责,但是能很好地找到平衡点。

  2、最少知识原则

  减少对象之间的联系:

  a、两个对象之间不必直接通信则不直接通信,通过第三方实现通信;

  b、如中介者模式和外观模式

  违反不一定是坏事:

  比如:$.ajax 和 $.post

  3、开放-封闭原则

  开放和封闭(对扩展开放,对修改关闭):

  a、当需要改变时,可以使用增加代码的方式,但不允许改动程序的源代码,比如组件有bug或不满足需求时;

  b、比如一个很老系统新的需求window.onload的时候需要统一打一下日志,如何处理?

  法1:使用jQuery,因为jQuery的事件可以监听多个;

  法2:重写onload方法,重写的时候先调它的方法,再调自己的方法。

  找出变化的地方很重要:

  a、挑选出最容易发生变化的地方进行抽象,来封闭这些变化;

  b、不可避免发生修改时,尽量修改容易修改的地方,如修改配置比修改源码简单。

  

  写在最后:本文为参加公司前端大牛分享整理所得,转载请注明出处或取得作者同意。

举个栗子学习JavaScript设计模式的更多相关文章

  1. JavaScript的学习--JavaScript设计模式的总结

    这篇博客只是自己对设计模式的理解的备忘~ 看完了<JavaScript设计模式>这本书,一直没有写博客记录一下,最近抽出时间来重读了一下,就顺便记录一下~ 如果你只是想粗略了解一下Java ...

  2. 为什么学习JavaScript设计模式,因为它是核心

    那么什么是设计模式呢?当我们在玩游戏的时候,我们会去追求如何最快地通过,去追求获得已什么高效率的操作获得最好的奖品:下班回家,我们打开手机app查询最便捷的路线去坐车:叫外卖时候,也会找附近最近又实惠 ...

  3. 学习javascript设计模式之中介者模式

    1.中介者模式的作用就是解除对象与对象之间的紧耦合关系.增加一个中介者对象后,所有的相关对象都通过中介者来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介对象即可.中介者使各对象之间耦合 ...

  4. 学习javascript设计模式之代理模式

    1.代理模式为一个对象提供一个代用品或占位符,以便控制对它的访问. 2.不用代理模式: 客户 -> 本体  使用代理模式:  客户 -> 代理 -> 本体 3.例子场景1 点击操作与 ...

  5. 学习javascript设计模式之发布-订阅(观察者)模式

    1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...

  6. 学习javascript设计模式之单例模式

    1.单例模式的核心是确保只有一个实例,并提供全局访问. 2.惰性单例 指的是在需要的时候才创建对象实例. 如在页面中创建唯一div 普通做法 var createDiv = (function(){  ...

  7. 学习javascript设计模式之装饰者模式

    1.装饰者模式定义:给对象动态添加职责的方式称为装饰者(decorator)模式. js如何实现装饰者模式 通过保存原函数引用方式改写某函数 window.onload = function(){al ...

  8. Javascript设计模式学习一

    学习Javascript设计模式之前,需要先了解一些相关知识,面向对象的基础知识.this等重要概念,以及掌握一些函数式编程的技巧. Js多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...

  9. 探索Javascript设计模式---单例模式

    最近打算系统的学习javascript设计模式,以便自己在开发中遇到问题可以按照设计模式提供的思路进行封装,这样可以提高开发效率并且可以预先规避很多未知的问题. 先从最基本的单例模式开始. 什么是单例 ...

随机推荐

  1. ADO.NET对象的详解

    1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ...

  2. Hyper-V3:虚拟机的配置

    在Hyper-V成功新建一台虚拟机,在正式使用之前,必须配置VM使用的硬件资源,并授予用户访问VM的权限等,本文罗列出一些常见的配置,供读者参阅. 一,为虚拟机分配使用的内存 在Hyper-V Man ...

  3. Android-armebi-v7a、arm64-v8a、armebi的坑

    先来一波扫盲: armeabi:针对普通的或旧的arm v5 cpu armeabi-v7a:针对有浮点运算或高级扩展功能的arm v7 cpu(32位ARM设备) arm64-v8a:64位ARM设 ...

  4. Android学习探索之Java 8 在Android 开发中的应用

    前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...

  5. 破解SQLServer for Linux预览版的3.5GB内存限制 (UBUNTU篇)

    在上一篇中我提到了如何破解RHEL上SQLServer的内存大小限制,但是Ubuntu上还有一道检查 这篇我将会讲解如何在3.5GB以下内存的Ubuntu中安装和运行SQLServer for Lin ...

  6. iOS微信里打开app,Universal Links

    这两天在弄分享,从第三方应用或者浏览器打开自己app的东西 传统的方式是通过URL Scheme的方式,但是iOS9以后又出了新的更完美的方式Universal Links. 传统的URL Schem ...

  7. c# 基础 object ,new操作符,类型转换

    参考页面: http://www.yuanjiaocheng.net/webapi/config-webapi.html http://www.yuanjiaocheng.net/webapi/web ...

  8. bzoj1584--DP

    题目大意:有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若 ...

  9. Linux下高cpu解决方案

    昨天搞定了一个十万火急的issue,客户抱怨产品升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,弄得我们 R&D压力很大,解决这个issue的任务分给了我,客 ...

  10. 使用四元数解决万向节锁(Gimbal Lock)问题

    问题 使用四元数可以解决万向节锁的问题,但是我在实际使用中出现问题:我设计了一个程序,显示一个三维物体,用户可以输入绕zyx三个轴进行旋转的指令,物体进行相应的转动. 由于用户输入的是绕三个轴旋转的角 ...