0.面向对象的设计模式与原则

2023-11-06

设计模式与面向对象

  • 面向对象设计模式解决的是“类与相互通信的对象之间的组织关系”,包括它们的角色、职责、协作方式几个方面;
  • 面向对象设计模式是“好的面向对象设计”,所谓“好的面向对象设计”是哪些可以满足==“应对变化,提高复用”==的设计
  • 面向对象设计模式是建立在对”面向对象“纯熟、深入的理解的基础上的经验性认识。掌握面向对象设计模式的前提是掌握”面向对象“。

面向对象编程语言的三大机制

  • 封装:隐藏内部实现
  • 继承:复用现有代码
  • 多态:改写对象行为

面向对象编程语言(OOPL)并非面向对象的全部

OOPL 没有回答面向对象的本质性问题:

  1. 我们为什么要使用面向对象?
  2. 我们应该怎样使用三大机制来实现”好的面向对象“?
  3. 我们应当遵循什么样的面向对象原则?

重新认识面向对象

  • 面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小;
  • 面向对象的方式更强调各个类的==“责任”==,“新增员工”类型不会影响原来员工类型的实现代码;
  • 对象是什么?
    • 从概念层面讲:对象是某种拥有责任的抽象;
    • 从规格层面讲:对象是一系列可以被其它对象使用的公共接口;
    • 从语言实现层面来看:对象封装了代码和数据
  • 怎么才能设计“好的面向对象”
    • 遵循一定的面向对象设计原则
    • 熟悉一些典型的面向对象设计模式

从设计原则到设计模式

  1. 针对接口编程,而不是针对实现编程
    • 客户无需知道所使用对象的特定类型,只需要知道对象拥有客户所期望的接口;
  2. 优先使用对象组合,而不是类继承
    • 类继承通常为“白箱复用”,对象组合通常为“黑箱复用”。继承在某种程度上破坏了封装性,子类父类耦合度高;而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低;
  3. 封装变化点
    • 使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。
  • **使用重构得到设计模式——设计模式的应用不宜先入为主。**一上来就使用设计模式是对设计模式最大的误用。没有一步到位的设计模式。
  • 不要把设计模式当成技巧

几条更具体的设计原则

1.单一职责原则(SRP)

定义:一个类应该仅有一个引起它变化的原因;

优点:

  1. 类的复杂性降低,实现什么职责都有清晰明确的定义;
  2. 可读性提高,复杂性降低,那当然可读性提高了;
  3. 可维护性提高,可读性提高,那当然更容易维护了;
  4. 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修
    改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大
    的帮助。
  5. 单一职责适用于接口、类,同时也适用于方法

**PS:**单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

2.里式替换原则(LSP)

定义:所有引用基类的地方必须能透明地使用其子类的对象(子类必须能够替换它们的基类)。

在面向对象的语言中,继承是必不可少的、非常优秀的语言机制。它存在非常明显优缺点。

优点:

  • 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
  • 提高代码的重用性;
  • 子类可以形似父类,但又异于父类;
  • 提高代码的可扩展性:很多开源框架的扩展接口都是通过继承父类来完成的;
  • 提高产品或项目的开放性。

缺点:

  • 继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
  • 降低代码的灵活性。子类必须拥有父类的属性和方法,让子类多了些约束;
  • 增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大段的代码需要重构。

里氏替换原则为良好的继承定义了一个规范,一句简单的定义包含了4层含义。

  1. 子类必须完全实现父类的方法

    注意:

    • 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。
    • 如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。
  2. 子类可以有自己的个性:以子类对象作为参数传递的地方,用父类对象作为参数传递可能产生类型异常;

    someObject.doSomething(new Son());  //可行
    someObject.doSomething((Son)new Father());  //不可行
    
  3. 子类在覆盖或实现父类的方法时前置条件(输入参数类型)应相同或者更宽松:在一个Invoker类中关联了一个父类,调用了一个父类的方法,子类可以覆写(Override)这个方法,也可以重载(Overload)这个方法,前提是要扩大这个前置条件,就是输入参数的类型宽于父类的类型覆盖范围。否则,代码逻辑可能发生混乱。

  4. 子类覆写或实现父类的方法时输出结果可以被缩小:父类的一个方法的返回值是一个类型T,子类的相同方法(重载或覆写)的返回值为S,那么里氏替换原则就要求S必须小于等于T,也就是说,要么S和T是同一个类型,要么S是T的子类。

采用里氏替换原则的目的:采用里氏替换原则的目的就是增强程序的健壮性,即使在项目升级时增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑。

3.依赖倒置原则(DIP)

定义:高层模块不应该依赖底层模块,二者都应该依赖于抽象;抽象不应该依赖于实现细节,实现细节应该依赖于抽象;更简单地可以理解为“面向接口编程”

具体表现为:

  • 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
  • 接口或抽象类不依赖于实现类;
  • 实现类依赖接口或抽象类。

实践

  • 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备;接口和抽象类都是属于抽象的,有了抽象才可能依赖倒置。
  • 变量的表面类型尽量是接口或者是抽象类;
  • 任何类都不应该从具体类派生;
  • 尽量不要覆写基类的方法;如果基类是一个抽象类,而且这个方法已经实现了,子类尽量不要覆写。类间依赖的是抽象,覆写了抽象方法,对依赖的稳定性会产生一定的影响。
  • 结合里氏替换原则使用:接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化。

4.接口隔离原则(ISP)

定义:不应该强迫客户程序依赖于它们不用的方法(客户端不应该依赖它不需要的接口/类间的依赖关系应该建立在最小的接口上)。

接口隔离原则是对接口进行规范约束,其包含以下4层含义:

  • 接口要尽量小:这是接口隔离原则的核心定义,不出现臃肿的接口(Fat Interface),但是“小”是有限度的,首先就是不能违反单一职责原则。
  • 接口要高内聚:高内聚就是提高接口、类、模块的处理能力,减少对外的交互。具体到接口隔离原则就是,要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也越少,同时也有利于降低成本。
  • 定制服务:定制服务就是单独为一个个体提供优良的服务。采用定制服务就必然有一个要求:只提供访问者需要的方法。
  • 接口设计是有限度的:接口的设计粒度越小,系统越灵活。但是,灵活的同时也带来了结构的复杂化,开发难度增加,可维护性降低,所以接口设计一定要注意适度。

5.迪米特法则(LoD)(LKP)

**定义:迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least KnowledgePrinciple,LKP),描述的是:一个对象应该对其他对象有最少的了解。**即一个类应该对自己需要耦合或调用的类的内部情况知道得最少。

迪米特法则对类的低耦合提出了明确的要求,其包含以下4层含义:

  • 只和朋友(类)交流:

  • 每个对象都必然会与其他对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系的类型有很多,例如组合、聚合、依赖等;

  • 朋友类的定义:出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类;

    • 类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不引入一个类中不存在的对象。
  • **朋友间也是有距离的:**一个类公开的public属性或方法越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大。迪米特法则要求类尽量不要对外公布太多的public方法和非静态的public变量,尽量多使private、package-private、protected等访问权限,以及final、readonly等关键字。

  • 是自己的就是自己的:如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。

  • 谨慎使用Serializable

迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度。

6.开放封闭原则(OCP):

定义:类模块应该是可以扩展的,但是不可修改(对扩展开放,对更改封闭)

  1. 开闭原则是最基础的一个原则,原则都是开闭原则的具体形态
  2. 开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。

软件开发中的变化可以归纳为以下三种类型:

  • 逻辑变化:只变化一个逻辑,而不涉及其他模块,比如原有的一个算法是a*b+c,现在需要修改为a*b*c,可以通过修改原有类中的方法的方式来完成,前提条件是所有依赖或关联类都按照相同的逻辑处理。
  • 子模块变化:各模块变化,会对其他的模块产生影响,特别是一个低层次的模块变化必然引起高层模块的变化,因此在通过扩展完成变化时,高层次的模块修改是必然的。
  • 可见视图变化:一个展示数据的列表,按照原有的需求是6列,突然有一天要增加1列,而且这一列要跨N张表,处理M个逻辑才能展现出来,这样的变化是比较恐怖的,但还是可以通过扩展来完成变化,这就要看我们原有的设计是否灵活。

开闭原则的重要性:

  1. 开闭原则对测试的影响:通过扩展来实现业务逻辑的变化,有利于单元测试。
  2. 开闭原则可以提高复用性:在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被复用的可能性就越大。
  3. 开闭原则可以提高可维护性:一款软件投产后,维护人员的工作不仅仅是对数据进行维护,还可能要对程序进行扩展,维护人员最乐意做的事情就是扩展一个类,而不是修改一个类。
  4. 面向对象开发的要求:万物皆对象,我们需要把所有的事物都抽象成对象,然后针对对象进行操作,但是万物
    皆运动,有运动就有变化,有变化就要有策略去应对。这就需要在设计之初考虑到所有可能变化的因素,然后留下接口,等待“可能”转变为“现实”。

如何使用开闭原则:

  1. 抽象约束:通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义
    1. 通过接口或抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
    2. 参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
    3. 抽象层尽量保持稳定,一旦确定即不允许修改。
  2. 元数据(metadata)控制模块行为:元数据是用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。
  3. 制定项目章程;
  4. 封装变化
    1. 第一,将相同的变化封装到一个接口或抽象类中;
    2. 第二,将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。

7.合成/聚合复用原则

尽量使用对象组合/聚合,而不是继承来达到复用:将已有的对象纳入新对象中,作为新对象的对象成员来实现,新对象可以调用已有对象的功能,从而达到复用。

类与类之间的六大关系

泛化

相当于继承的相对概念。如下,Tiger是对Animal的继承,Animal是对Triger的泛化

public class Animal
{
    private char _gender;
}
public class Tiger : Animal
{
    private string _name;
}

实现

类与接口的关系。类实现了接口。如下,Tiger实现了IClimb。

public interface IClimb
{
    void Climb();
}
public class Tiger : IClimb
{
    private string _name;
    public void Climb()
    {
        //具体实现老虎爬树
    }
}

组合

组合是整体与部分的关系,是强拥有关系。部分没有独立的生命周期,与整体的生命周期保持一致。组合是把部分作为整体类的对象。

如下,Tiger是整体,Leg是部分,二者是组合关系。

public class Tiger
{
    private Leg _leg;
    public Tiger(Leg leg)
    {
        this._leg = leg;
    }
}
public class Leg
{
    private int _count;
}

聚合

聚合也是整体与部分的关系,但是个体有独立的生命周期,是弱拥有关系。聚合是把个体对象的指针(引用)作为整体类的属性。

如下,TigerGroup是整体,Tiger是部分,二者是聚合关系。

public class Tiger
{
    private Leg _leg;
}
public class TigerGroup
{
    private Tiger[] tigers;
}

关联

关联是一种拥有关系,它使一个类知道另一个类的属性和方法。

如下,Tiger和Food是关联关系。

public class Tiger
{
    private Food food;
}
public class Food
{
    public string FoodName;
}

依赖

依赖是一种使用关系。如下,Tiger和Water是依赖关系。具体设计中常将Water写作接口,然后用接口注入。

public class Tiger
{
    public void Drink(Water water)
    {
        //喝水
    }
}
public class Water
{
    private float _weight;
}

模式分类

  • 从目的来看:
    1. 创建型模式:负责对象创建
    2. 结构型模式:处理类与对象间的组合
    3. 行为型模式:类与对象交互中的职责分配
  • 从范围来看:
    1. 类模式处理类与子类的静态关系
    2. 对象模式处理对象间的动态关系

如何使用设计模式

一个系统中该如何采用”设计模式“进行开发,需要对用户需求中各模块之间的关系不断分析而迭代演化出来的。

在软件开发过程中,随着不断分析和开发,对软件体系结构进行抽象和细节的划分,从而区分主次。系统的”主线“是抽象出来的主体结构(接口);”次(支线)“是对抽象进行具体实现部分。

在软件开发中,将”主线“接口稳定下来,那么在后续维护过程中,就只需更改针对接口的具体实现就可以。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

0.面向对象的设计模式与原则 的相关文章

  • c语言实现面向对象编程(const * ,* const)

    c语言实现面向对象编程 面向对象思想 封装 继承 多态 代码实现 函数签名及返回值的约定 const 重载 参考了onlyshi的博客代码 orz传送门 参考了嵌入式实践一些代码 这里就不加了 面向对象思想 面向对象编程 OOP 并不是一种
  • Spring源码学习之BeanDefinition源码解析

    本文作者 磊叔 GLMapper本文链接 https juejin cn post 6844903553820000269 Bean的定义主要由BeanDefinition来描述的 作为Spring中用于包装Bean的数据结构 今天就来看看
  • Java复习-25-单例设计模式

    单例设计模式 目的 使用场景 在实际开发下 会存在一种情况 某一种类在程序的整个生命周期中 只需要实例化一次就足够了 例如 系统数据类 由于操作系统只有一个 因此在程序初始化时该类只需要实例化一次 之后的系统数据更改都是在这一个实例化对象中
  • 行为型模式-策略模式

    package per mjn pattern strategy 抽象策略类 public interface Strategy void show package per mjn pattern strategy 具体策略类 用来封装算法
  • 离散仿真引擎基础作业与练习

    作业内容 一 简答题 1 解释 GameObjects 和 Assets 的区别与联系 2 下载几个游戏案例 分别总结资源 对象组织的结构 3 使用 debug 验证 MonoBehaviour 基本行为或事件触发条件 4 了解 GameO
  • 设计模式学习笔记(一)之单例模式

    单例模式 作用 保证一个类只有一个实例 并且提供访问这个实例的全局访问点 应用场景有 数据库连接池 spring中 Bean默认是单例 Servlet中 每一个Servlet是单例 配置文件的类 一般是单例 优点 单例只生成一个实例 减少系
  • C++设计模式(二)观察者模式

    1 观察者模式知识点 1 定义 定义对象间的一种一对多的依赖关系 当一个对象的状态发生改变的时候 所有依赖它的对象都得到通知并自动更新 2 动机 将一个系统分割成一系列相互协作的类有一个常见的副作用 需要维护相关对象间的一致性 我们不希望为
  • 设计模式——原型模式

    原型模式顾名思义 就是指以某个实例为原型 copy出一个新的实例 该实例属性与原型相同或者是类似 很多时候 我们需要创建大量的相同或者相似的对象 如果一个个用new 构造函数的形式去创建的话比较繁琐 就像孙悟空要想变出成千上万个猴子猴孙总不
  • 设计模式之享元模式

    一 背景 在面向对象程序设计过程中 有时会面临要创建大量相同或相似对象实例的问题 创建那么多的对象将会耗费很多的系统资源 它是系统性能提高的一个瓶颈 例如 围棋和五子棋中的黑白棋子 图像中的坐标点或颜色 局域网中的路由器 交换机和集线器 教
  • 面向过程和面向对象的语言有哪些,以及优缺点(一篇文章让你理解)

    C语言是面向过程的 而C python java是面向对象的 面向过程的编程思想将一个功能分解为一 个一个小的步骤 我们通过完成一个一 个的小的步骤来完成一个程序 优点 这种编程方式 符合我们人类的思维 编写起来相对比较简单 缺点 但是这种
  • 设计模式--组合模式

    组合模式 又叫部分整体模式 属于结构型模式 基本原理 以树形的结构将相似的对象组合起来 主要流程 1 创建对象 2 在对象中设置用来存放下一级相似对象的数据结构 3 在对象中设置增删改查等功能 注意 这种模式和数据结构中的树形结构相似 in
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • 行为型模式-状态模式

    package per mjn pattern state after 环境角色类 public class Context 定义对应状态对象的常量 public final static OpeningState OPENING STAT
  • 设计模式 -- 工厂模式(Factory Pattern)

    简单工厂模式 Simple Factory Pattern 根据传入的参数决定实例化哪个对象 优点 不直接在客户端创建具体产品的实例 降低了耦合性 缺点 违反了开闭原则 对扩展开放 对修改关闭 不容易形成高内聚松耦合结构 每当我们增加一种产
  • 设计模式--Abstract server模式 VS Adapter 模式

    适配器类似于现实世界里面的插头 通过适配器 我们可以将分属于不同类的两种不同类型的数据整合起来 而不必去根据某一需要增加或者修改类里面的方法 Adapter mode和Proxymode的区别 Proxy的关注点是职能转移 通过引入Prox
  • 设计模式七大原则

    1 设计模式的目的 编写软件过程中 程序员面临着来自耦合性 内聚性以及可维护性 可扩展性 重用性 灵活性 等多方面的挑战 设计模式是为了让程序 软件 具有更好 1 代码重用性 即 相同功能的代码 不用多次编写 2 可读性 即 编程规范性 便
  • 设计模式学习笔记-工厂模式

    设计模式学习笔记 工厂模式 作用 实现了创建者和调用者的分离 详细分类 简单工厂模式 用来生产同一等级结构中的任意产品 对于增加新的产品 必须要扩展已有的代码 工厂方法模式 用来生产同一等级结构中的固定产品 支持增加任意产品 抽象工厂模式
  • [C++]外观模式

    外观模式 Facade Pattern 隐藏系统的复杂性 并向客户端提供了一个客户端可以访问系统的接口 这种类型的设计模式属于结构型模式 它向现有的系统添加一个接口 来隐藏系统的复杂性 这种模式涉及到一个单一的类 该类提供了客户端请求的简化
  • [设计模式]模板方法模式(Template Method)

    1 意图 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 2 动机 其实就是如意图所描述的 算法的骨架是一样的 就是有些特殊步骤不一样 就可以
  • JavaScript设计模式-02-单例模式

    Javascript 设计模式 02 单例模式 简介 单例就是保证一个类只有一个实例 实现的方法一般是先判断实例是否存在 如果存在直接返回 如果不存在就创建了再返回 确保了一个类只有一个实例对象 在JavaScript里 单例作为一个命名空

随机推荐

  • SpringCache使用

    SpringCache使用 1 引入依赖 引入springcache依赖
  • three.js坐标轴辅助器AxesHelper

    一 效果图 二 添加坐标轴辅助器 使用three js 通过以下代码可以添加坐标轴辅助器 创建坐标轴辅助器 var axesHelper new THREE AxesHelper 5 添加到场景中 scene add axesHelper
  • 私有云平台管理

    更改主机名 controller hostnamectl set hostname controller compute hostnamectl set hostname compute 更改hosts文件 vi etc hosts 插入以
  • Java NIO通信编程

    NIO即非同步非阻塞式IO 有如下几个特点 1 创建一个线程负责处理IO事件和IO事件的分发 2 事件驱动机制 事件到达之后触发 3 线程之间通过wait notify等方式通信 减少线程间切换 NIO客户端和服务端需都维护一个管理通道的对
  • flutter加载不同分辨率本地图片

    flutter移动开发怎么加载本地图片 首先在该项目根目录也就是和ios android同级创建一个images文件夹用来存放图片资源 然后放入需要加载的图片资源例如ic phone png 然后在项目目录下找到pubspec yaml文件
  • 【定量分析、量化金融与统计学】统计推断基础 番外(1)---T table与Z table的值

    目录 一 前言 二 T table 三 Z table 一 前言 为了方便之后的例题讲解 这里放上T tabel和Z table的值 怎么查表 本篇中会直接讲 所以这里就只看表格就行 本篇为工具篇 二 T table 我们给两个版本 适合用
  • Redis学习笔记:数据结构和命令

    本文是自己的学习笔记 主要参考资料如下 马士兵 4 Redis的五大数据类型 1 1 String 1 1 1 String 类型的命令 1 1 2 存储对象 1 2 List 1 2 1 List基本命令 1 2 2 List高级命令 1
  • linux 提高文件读写速度 mmap,【EA字符串Linux面试题】面试问题:kafka读写… - 看准网...

    传统IO 缓存IO 传统IO也就是缓存IO 数据先从磁盘复制到内核空间缓冲区 然后从内核空间缓冲区复制到应用程序的地址空间 这里的内核缓冲区也就是页缓存 PageCache 是虚拟内存空间 读操作 操作系统检查内核的缓冲区有没有需要的数据
  • QT结构体中定义QString注意点

    当需要进行多进程通讯时 结构体中出现字符串时尽量采用C 标准类型 尽量少用QT特有类型QString字符串 尽量采用char 类型替代 这样在多进程通讯时 可直接通过memcpy直接复制内存的方式 而不用担心内存异常问题 由于QString
  • 动手搭建第一个小程序音视频Demo

    欢迎大家前往云 社区 获取更多腾讯海量技术实践干货哦 作者 小程序音视频产品经理 腾讯云提供了全套技术文档和源码来帮助您快速构建一个音视频小程序 但是再好的源码和文档也有学习成本 为了尽快的能调试起来 我们还提供了一个免费的一键部署服务 您
  • 华为OD机试 - 最长连续子序列(Java )

    题目描述 有N个正整数组成的一个序列 给定整数sum 求长度最长的连续子序列 使他们的和等于sum 返回此子序列的长度 如果没有满足要求的序列 返回 1 输入描述 第一行输入是 N个正整数组成的一个序列 第二行输入是 给定整数sum 输出描
  • 02 电阻容模型的创建

    打开状态栏 画电阻 电容的封装 实操要点 1 SCH Library一定要先选中 出现元件库的列表 2 放置完元件可以按ESC取消 3 Ctrl C V可以复制粘贴用 4 多余的线可以使用Delete删除 5 可以按鼠标右键轻微的拖动屏幕
  • ViLT:最简单的多模态Transformer

    原文链接 感谢原作者 ViLT 最简单的多模态Transformer 陀飞轮 复
  • 两台外网计算机远程桌面访问(内网穿透)

    背景 如图所示 项目中需要远程访问项目现场的外网计算机 通过外网计算机再访问到现场内网环境中的另外一台计算机 原计划通过市面上的远程桌面软件 如向日葵 ToDesk AnyDesk等 建立两台外网计算机的远程连接 在使用windows自带的
  • UmiJS介绍--mock(四)

    umi 里约定 mock 文件夹下的文件即 mock 文件 文件导出接口定义 支持基于 require 动态分析的实时刷新 支持 ES6 语法 以及友好的出错提示 1 引入 Mock js Mock js是常用的辅助生成模拟数据的第三方库
  • 编写过滤器jar包并植入到项目中

    公司有项目有个需求 就是希望可以写一个统一的权限管理 每次开发新项目的时候 可以通过添加依赖包进行权限的获取 验证 至于为什么不使用aop 拦截器二使用过滤器 是因为在java中 如果3者同事存在 最先执行的是过滤器 一 新建第三方过滤器j
  • QT 使用 qtasome图标 (python版)

    首先安装 qtawesome 库 然后到图标库找到需要的图标 图标名称为 fa xxx 图标库链接 http www fontawesome com cn faicons 在 retranslateUi 模块中 对相应 按钮 进行操作 运行
  • 6_机器翻译与Seq2Seq模型

    文章目录 一 Sequence to Sequence Model Seq2Seq 1 1 Machine Translation Data 机器翻译数据 1 2 Tokenization Build Dictionary 分词和建造字典
  • uva 1601 The Morning after Halloween code2

    题目 The Morning after Halloween 题意 有n个用小写字母表示的鬼和一张地图 每个鬼都要移动到对应的大写字母 两个鬼的位置不能在一次移动中交换 问最少步数 思路 双向bfs 此题还可以单向bfs 见code1 1
  • 0.面向对象的设计模式与原则

    面向对象的设计模式与原则 设计模式与面向对象 面向对象编程语言的三大机制 面向对象编程语言 OOPL 并非面向对象的全部 重新认识面向对象 从设计原则到设计模式 几条更具体的设计原则 1 单一职责原则 SRP 2 里式替换原则 LSP 3