design(未完)

225 阅读5分钟

学习设计,得先学下面向对象四个特点

  • 抽象:通俗点,就是参数接口放接口,或者抽象类,反正就是用interface或者abstract定义的东西。别人调用的时候,就可以传得很灵活。只要实现了对应的interface或abstract定义的东西都行。
  • 继承:这个没啥说的,就是提高代码的复用。子类没有的函数会依次往父类上找。
  • 封装:类的方法,属性都有修饰符。控制访问权限。 public 都可以用,管它同不同包
    protected 除了 不同包中的非子类,其他都可以
    default 只要不同包,就不能访问
    private 只有自己的类里可用
  • 多态: 通俗的讲就是,参数如果有子类,那子类的实例也要能当参数,传在那个地方。否则就是不满足多态的特点。

设计原则-SOLID

  • O-对修改封闭,对拓展开放
// 不好,修改的时候要去改方法内部的代码
switch (customer.rank) {
            case 'member':
                return this.price * .8;
            case 'vip':
                return this.price * .6;
            default:
                return this.price;
 }
 // 好的设计
 // 在产生customer的地方,应该传入折扣,然后存储count,用到的时候直接取。
 // 在新增顾客种类的时候,直接new Customer('vvvip', .1);
return this.price * customer.getDiscount();
 
  • S-单一职责原则:这个简单,一个类或者模块只负责一个功能。

  • L-里氏替换原则:跟之前的多态有点像,所有引用基类的地方必须能使用其子类的对象(有子能替父)

  • D-依赖倒置原则:依赖于抽象,而不依赖于具体实现。比如一个类里,需要使用别的类的实例作为自己的属性。我们在声明的时候,尽量应该写层次高的抽象层类.通俗点就是放interface或者abstract定义的东西。

  • I-接口隔离原则:接口尽量细化,而且接口中的方法尽量的少,类似于单一职责原则,更关注接口

  • 迪米特法则:简单讲就是公司老板,中层领导,搬砖员工,清洁工。老板不管所有人,老板类只持有中层领导的对象实例作为属性,中层领导类里持有板砖的,一层一层的下去。

  • 合成复用原则:尽量组合/聚合的方式,不使用继承 ( ps:简单解释下组合聚合,A类属性有一个B类的Array<B>,就是聚合,只有一个B对象就是单向关联 )

SI差不多,LD也差不多

工厂模式

  • 简单工厂:函数根据接收的参数,直接返回目标对象
  • 工厂方法:在简单工厂的基础上,每个目标对象多了一个对应的目标对象工厂类,创建的时候由每个目标对象工厂类创建对象。
  • 抽象工厂:当对象种类需要细分的时候,就创建一个抽象工厂。能创建拿铁对象,再来一个星巴克拿铁工厂,再来一个星巴克拿铁咖啡类,创建对应的星巴克拿铁工厂星巴克拿铁咖啡类.
    eg:咖啡:拿铁 不同种类,星巴克拿铁 不同公司。

    之前焦点都在咖啡上,现在抽象工厂的能力了。

策略模式

  • 其实这个模式只要我们改一下平时编码的习惯,每天都能用上。主要可以用来消除if else 或 swith case
class Customer{
    constructor(type) {
        this.type=type;
    }
    pay(amount) {
        if (this.type == '会员顾客') {
            return amount*.9;
        }else if (this.type == 'VIP顾客') {
            return amount*.8;
        } 
        return amount;
    }
}
new Customer('普通顾客').pay(100);
new Customer('会员顾客').pay(100);
new Customer('VIP顾客').pay(100);
  • 优化
    //new Customer()的时候传不同的字符串进去区分,
    //不如不直接在这个地方把if else的根掐掉,把对应的折扣写死在对应的类里,不要传字符串去if lese
    new NormalCustomer().pay(100);
    new MemberCustomer().pay(100);
    new VIPCustomer().pay(100);

适配器模式

  • 通俗理解:以前有个类,类里有个方法,参数或者返回值不满足要求。(原则是不能直接改老方法里的源代码)
    适配器做法: 写一个类,持有老的类的对象,作为自己的属性,自己再定义跟老方法名不同的方法,在这个方法里,调用老的方法,在调用前修改参数,或在调用后修改返回值,只要能满足新需求。都叫设配器设计模式。

观察者模式

  • 被观察者里存了很多Observers,被观察者自己在发生了某些事件后,遍历存的Observers,然后notify每个Observers
  • 发布订阅, 相比与观者者模式,多了一个中间人. 订阅是通过中间人订阅的, 发布也是通过中间人发布的.两者都持有中间人的引用

迭代器模式

  • 我有很多数组,数组里存的对象结构不一样, 因为简单遍历后得到的对象,可能还不是我们最终想要的结果,可能只是里面的某一个属性.我们就提前给每个类实现一个iterator方法,返回一个可以不段next()的对象,来统一遍历.

外观模式

  • 感觉是个人都会用.(Calculator的sum minus multiply是别的类的实例的功能.)
class Sum {
    sum(a, b) {
        return a + b;
    }
}
class Minus {
    minus(a, b) {
        return a - b;
    }
}
class Multiply {
    multiply(a, b) {
        return a * b;
    }
}
class Calculator {
    sumObj
    minusObj
    multiplyObj
    constructor() {
        this.sumObj = new Sum();
        this.minusObj = new Minus();
        this.multiplyObj = new Multiply();
    }
    sum(...args) {
        return this.sumObj.sum(...args);
    }
    minus(...args) {
        return this.minusObj.minus(...args);
    }
    multiply(...args) {
        return this.multiplyObj.multiply(...args);
    }
}
let calculator = new Calculator();
console.log(calculator.sum(1, 2));
console.log(calculator.minus(1, 2));
console.log(calculator.multiply(1, 2));

装饰器模式 跟 代理模式

  • 一句话讲,就是装饰者类,跟代理类,都有一个属性,是被装饰者、或者被代理类的对象,这样就可以控制 在被调用的时候,装饰者类,跟代理类可以在这个函数调用前干点别的。调用后干点别的。或者直接不调用都行。
class A { 
    fn1(){}
}

class Decorater(Or Proxy) {
  constructor(a) {
    this.a = a;
  }
  
  fn1(){
    // 调用前,加一坨代码
    this.a.fn1()
    // 调用后,加一坨代码
  }
}

new Decorater(new A).fn1()
new Proxy(new A).fn1()
  • 这俩设计模式咱不要讲区别, 意义不大.