设计模式

138 阅读4分钟

设计原则

参考:juejin.cn/post/715906…

五大设计原则:SOLID

  1. 单一职责原则(S:SRP(The Single-Responsibility Principle) ):表示对象应该具有一种单一功能的原则,降低各个功能之间的耦合,保证高内聚、低耦合的功能,就是说对于类和方法,职责应该尽量单一;

    // 校验邮箱
    const validateEmail = () => {
            return new Promise((resolve, reject) => {
                    // todo ...
                    resolve(true)
            })
    }
    
    // 校验年龄
    const validateAge = () => {
            return new Promise((resolve, reject) => {
                    // todo ...
                    resolve(true)
            })
    }
    
  2. 开放-封闭原则(O:OCP(The Open/Closed Principle):表示“程序中对于扩展开发,对于修改封闭”,一个类或者函数确定其能力之后,便不能再对其原有能力进行修改,只能在其原有功能之上进行扩展新的能力);

    /** 
     * 校验通过走 resolve, 不通过走 reject
    */
    const validate = () => {
            return new Promise((resolve, reject) => {
                    Promise.all([validateEmail(), validateAge()]).then(res => {
                            console.log('校验成功', res);
                            resolve(true)
                    }).catch(err => {
                            console.log('校验失败',err);
                            resolve(err)
                    })
            })
    }
    
    /** 
     * 提交数据
    */
    const submit = async () => {
            // 1. 校验数据
            const pass = await validate()
            console.log('pass', pass);
    
            if(pass) {
                    // 2 提交数据
            }else {
                    // todo ...
            }
    }
    
    // 增加一种校验
    // 校验时间
    const validateTime = () => {
            return new Promise((resolve, reject) => {
                    // todo ...
                    resolve(true)
            })
    }
    
  3. 里氏替换原则(L:LSP(The Liskov Substitution Principle) ):表示“程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换”,基类能够使用的地方,子类都可以完全覆盖、替换基类,使用基类和子类都不影响程序的正常运转,功能完全一致,主要强调的就是继承的实现。

    class Cat {
            constructor(name) {
                    this.name = name;
            }
    
            eat() {}
    }
    
    class BritishShorthair extends Cat {
            constructor(name) {
                    super(name);
            }
    
            eat() {}
    }
    
    const animal = new Cat("猫类");
    const bs = new BritishShorthair("英短");
    
    const my = {
            pet(p: Cat) { // 限制传递是Cat或者Cat的子类
                    console.log(`我的宠物是${p.name}`);
            }
    }
    
  4. 接口隔离原则(I:ISP(The Interface Segregation Principle) ):表示一个接口应该拥有尽可能少的行为,保持其单一独立,避免出现胖接口。对于不同的功能的模块分别使用不同接口,而不是使用同一个通用的接口。

    // 不好的例子
    public interface IAnimal {
        void run();
        void fly();
        void swim();
    }
    
    public class bird implements IAnimal{
        @Override
        public void run() {
    
        }
    
        @Override
        public void fly() {
            System.out.println("bird fly");
        }
    
        @Override
        public void swim() {
    
        }
    }
    
    // 优化
    public interface IFlyAnimal {
        void fly();
    }
    
    public interface IRunAnimal {
        void run();
    }
    
    public class bird implements IFlyAnimal{
        @Override
        public void fly() {
            System.out.println("bird fly");
        }
    }
    
  5. 依赖倒置原则(DIP(The Dependency-Inversion Principle)):高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖于抽象,使用方只关注接口而不关注具体类的实现;

    // 一般
    public class User {
        public void pay(Course course,Integer payType){
            //获取到课程的价格
            Double price = course.getPrice();
            switch (payType) {
                case 1 -> //支付宝
                        //调用支付宝支付sdk
                        System.out.println("支付宝支付了" + price + "元");
                case 2 ->  //微信支付
                        //调用微信支付sdk
                        System.out.println("微信支付了" + price + "元");
                default -> {
                }
            }
        }
    
    }
    
    // 优化
    public interface IPay {
        void pay(Course course);
    }
    
    public class AliPay implements IPay{
        @Override
        public void pay(Course course) {
            //调用支付宝支付sdk
            System.out.println("支付宝支付了" + course.getPrice() + "元");
        }
    }
    
    public class WeixinPay implements IPay{
        @Override
        public void pay(Course course) {
            //调用微信支付sdk
            System.out.println("微信支付了" + course.getPrice() + "元");
        }
    }
    
    public class User {
        public void pay(IPay pay,Course course){
            pay.pay(course);
        }
    
    }
    
    public class Test {
        public static void main(String[] args) {
            User user = new User();
            Course course = new Course(100.0);
            user.pay(new WeixinPay(),course);
            user.pay(new AliPay(),course);
        }
    }
    

另外加两个原则:

  1. 迪米特原则(Law of Demeter LoD)是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则(Least Knowledge Principle,LKP)

  2. 合成复用原则(Composite/Aggregate Reuse Principle,CARP)是指尽量使用对象组合(has-a)/ 聚合(contanis-a),而不是继承关系达到软件复用的目的。

设计模式

参考:blog.csdn.net/LoveLion/ar…

创建型模式

简单工厂模式

image.png

通过给工厂传入参数,输出不同的内容

工厂模式

image.png

抽象工厂模式

image.png

可以通过反射简化工厂选择判断;

单例模式

image.png

单例的理解

单例创建方式

  1. 不考虑线程,可用静态变量
  2. 考虑线层,用@synchronizeddispatch_once

原型模式

image.png

深拷贝和浅拷贝

建造者模式

image.png

结构型模式

适配器模式

image.png

相当于翻译官,将一个转换为另一个需要的对象

装饰器模式

image.png

将需要装饰的内容,给到具体的装饰器,完成装饰任务

代理模式

image.png

外观模式

image.png

提供一个对外的接口,使其比较简单调用负责的逻辑,无需关心内部的具体实现。

桥接模式

image.png

实现可能有多角度的分类,使每个分类的变化独立分开,减少耦合。

组合模式

image.png

树枝节点和叶子节点具有相同的访问和使用规则。

享元模式

image.png

缓存池,如UITableViewCell

行为型模式

策略模式

image.png

定义了算法家族,彼此之间可以互相替换

模板方法模式

image.png

将不变的放到父类,将变化的放到子类去实现。

观察者模式

image.png

建立1对多的依赖关系

迭代器模式

image.png

数组遍历

责任链模式

image.png

设置责任关联者,当前无法处理,则转交给关联者。

命令模式

image.png

命令发起者(Invoker)发布一个命令(Command),命令的接收者(Reciver)执行命令;

备忘录模式

image.png

状态模式

image.png

将各种状态的转移逻辑分布到State中,减少条件分支判断

访问者模式

image.png

中介者模式

image.png

通过中介来传递多方消息;

解释器模式

image.png

示例

image.png