设计模式(一) | 青训营笔记

155 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第7天

设计模式(上)

OOP七大原则

  • 开闭原则:添加新功能只能添加新代码不要修改原内容
  • 里氏替换原则:子类值扩展父类功能,不要改变父类的原功能
  • 依赖导致原则:抽象不依赖细节,细节应该依赖抽象,面向接口编程而不是面向实现编程,以降低程序之间的耦合性
  • 单一职责原则:一个对象尽量只做一件事,以控制类的粒度大小,提高其内聚性
  • 接口隔离原则:要为各个类建立其专用接口
  • 迪米特法则:两个对象之间不要直接沟通,尽量用第三方转发来沟通(get、set)
  • 合成复用原则:尽量先使用组合或聚合等关联来实现,其次才考虑用继承关系实现

创建型模式

单例模式

  • 用处:多个线程同时操作一个文件时,就必须在同个实例上进行
  • 做法:将构造器私有,所以每次调用都是同一个实例
  • 饿汉式单例

    • 优点:线程安全,实现简单,没加锁所以效率高
    • 缺点:类被加载时就会初始化,造成空间浪费,易产生垃圾对象
    • 例:
        public class HungryMan
        {
           private static HungryMan hungryMan = new HungryMan();
           private HungryMan(){ }
           public static HungryMan getInstance(){
              return hungryMan;
           }
        }
    
  • 懒汉式单例

    • 优点:第一次调用时才会初始化,避免浪费内存
    • 缺点:不加锁的时候线程不安全,但加了锁线程效率太低
    • 例:
    public class LazyMan
    {
        private static LazyMan lazyMan;
        private LazyMan(){}
        public static synchronized LazyMan getInstance(){
            if(lazyMan == null){
                lazyMan = new LazyMan();
            }
            return lazyMan;
        }
    }
    
  • 双重检测锁的懒汉式单例模式(DCL,即 double-checked locking)

    • 优点:多线程时还能保持高性能
    • 缺点:可以被反射破坏,会面临反射破坏问题
    • 例:
    private volatile static LazyMan lazyMan;
    public static LazyMan getInstance(){
        if(lazyMan == null){
           synchronized (LazyMan.class){//双重锁
              if(lazyMan == null){
                  lazyMan = new LazyMan();
              }
           }
        }
        return lazyMan;
    }
    



工厂模式

  • 作用:实现了创建者和调用者的分离

  • 原理:

    • 实例化对象不再使用new而是使用工厂方法。
    • 创建对象时不会对客户端暴露创建逻辑
    • 用户只需要告诉工厂即可获得实例,而不需要自己去设置参数
  • 简单工厂模式

    • 原理:多个同等级结构的类继承同个接口,简单工厂可以生产这几个类的实例
    • 流程:用户传入指令给工厂,工厂根据指令将类实例化后返回给用户
    • 缺点:增加新类时需要改变工厂类的代码,不符合开闭原则
    • ps:由于工厂内的方法都是静态方法,故又称静态工厂模式
  • 工厂方法模式

    • 原理:多个类继承同个接口后,每个类有独自的工厂
    • 流程:用户调用想要的类的工厂以获得目标类的实例
      • 例:Car car = new CarWuling().getCar();
    • 优点:符合OPP七大原则,在设计模式上更科学合理
    • 缺点:代码量太大,故实际开发上简单工厂模式更常用
  • 抽象工厂模式

    • 定义:抽象工厂提供了一个创建一系列相关或者相互依赖对象的结构,无需制定他们的具体类
    • 解释:抽象工厂就是工厂的工厂(加一层)
    • 原理:用一个超级工厂创建其他工厂 微信图片_20220802193718.png
    //超级工厂
    public interface SuperFactory
    {
        Phone phoneFactory();
        Router routerFactory();
    }
    
    //品牌
    public class HuaweiFactory implements SuperFactory
    {
        @Override
        public Phone phoneFactory() {
            return new Phone();
        }
        @Override
        public Router routerFactory() {
            return new Router();
        }
    }
    



建造者模式

  • 定义:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示
  • 作用:用户只需要给定复杂对象的类型和内容,建造者就会按顺序创建复杂对象,从而把内部的建造过程和细节隐藏起来
  • 关系:
    • 建造者:创建和提供实例
    • 指挥者:管理建造出来的实例的依赖关系。
  • 原理:用户实例化建造者,用指挥者控制建造者建造的顺序

微信图片_20220802211601.png 13b0940e-d1d7-4b17-af4f-b70cb0a75e08.png

  • 应用场景:需要生成的产品中有复杂的内部结构
  • 例:
    • 产品:
    public class Product
    {
       private String a;
       private String b;
    
       public String getA() {
          return a;
       }
       public void setA(String a) {
          this.a = a;
       }
       public String getB() {
          return b;
       }
       public void setB(String b) {
          this.b = b;
       }
    }
    
    • 建造者抽象类
    public interface Worker
    {
       public void setA();
       public void setB();
       public Product getPhone();
    }
    
    • 建造者
    public class Builder implements Worker
    {
       private Product product;
       public Builder() {
          product = new Product();
       }
       @Override
       public void setA() {
          product.setA("aaa");
       }
       @Override
       public void setB() {
          product.setB("bbb");
       }
       @Override
       public Product getPhone() {
          return product;
       }
    }
    
    • 指挥者
    public class Director
    {
       public Product create(Builder builder){
          builder.setA();
          builder.setB();
          return builder.getPhone();
       }
    }
    
    • 用户
    public class TestBuilder
    {
       public static void main(String[] args)
       {
          Director director = new Director();
          Builder builder = new Builder();
          Product product = director.create(builder);
       }
    }