精华内容
下载资源
问答
  • 关系模式优化主要思想及方法
    千次阅读
    2022-03-23 19:11:32

    1、定义

    模板方法模式的定义:定义一个操作中的算法的框架,将一些步骤延迟到子类中。使得子类可以不改变算法的结构即可重定义算法的某些特定步骤。

    模板方法模式可以说是最简单的一个设计模式了,只需要一个抽象类的继承就可以实现,我们平时也一直在使用,但是你可能不知道这种设计模式的名字叫做模板方法模式。


    2、类图

    模板方法模式的通用类图很简单,仅仅使用了Java的继承机制,如下:

    其中,AbstractClass叫做抽象模板 它的方法分为两类:

    1. 基本方法,也叫做基本操作 是由子类实现的方法并且在模板方法中被调用。
    2. 模板方法,可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻 。

    ConcreteClass1和ConcreteClass2叫做具体模板,实现父类所定义的一个或多个抽象方法。

    3、代码实现

    模板方法模式 的Java代码实现如下:

    //抽象模板类
    public abstract class AbstractClass {
    	//基本方法,尽量为protected类型,符合迪米特法则, 不需要暴露的属性或方法尽量不设置为protected类型。实现类若非必要,尽量不扩大父类中的访问权限。
    	protected abstract void doSomething();
    	//基本方法
    	protected abstract void doAnything();
    	//模板方法  为了防止恶意的操作,一般模板方法都加上final关键字,不允许被覆写。
    	final public void templateMethod(){
    		//用基本方法 完成相关的逻 
    		this.doAnything();
    		this.doSomething();
    	}
    }
    //具体模板类
    public class ConcreteClass1 extends AbstractClass {
    	//实现基本方法
    	protected void doAnything() {
    		//业务逻辑处理
    	}
    	protected void doSomething() {
    		//业务逻辑处理
    	}
    }
    public class ConcreteClass2 extends AbstractClass {
    	//实现基本方法
    	protected void doAnything() {
    		//业务逻辑处理
    	}
    	protected void doSomething() {
    		//业务逻辑处理
    	}
    }
    //场景类
    public class Client {
    	public static void main(String[] args) {
    	AbstractClass class1 = new ConcreteClass1();
    	AbstractClass class2 = new ConcreteClass2();
    	// 用模板方法
    	class1.templateMethod();
    	class2.templateMethod();
    	}
    }
    
    

    4、特点

    优点
    1、它封装了不变部分,扩展可变部分;把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
    2、它在父类中提取了公共的部分代码,便于代码复用。
    3、部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

    缺点
    1、对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,间接地增加了系统实现的复杂度。
    2、父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
    3、由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。


    5、适用场景

    模板方法模式通常适用于以下场景:
    1、算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
    2、当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
    3、当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展(多用于代码重构中)。

    6、钩子函数

    所谓钩子函数,就是在抽象模板类中定义一个具体方法,这个具体方法的返回值会影响模板方法的流程,同时子类可以重写这个方法,从而影响父类中模板方法的执行。

    带钩子函数的模板方法设计模式的Java代码实现如下:

    //抽象模板类
    public abstract class AbstractClass {
    	protected abstract void doSomething();
    	protected abstract void doAnything();
    	//钩子函数
    	protected boolean isDo(){
    		return true;
    	}
    	final public void templateMethod(){
    		//用基本方法 完成相关的逻 
    		this.doAnything();
    		//根据钩子函数的执行结果执行不同的操作
    		if(this.isDo())
    			this.doSomething();
    	}
    }
    //具体模板类
    public class ConcreteClass1 extends AbstractClass {
    	//实现基本方法
    	protected void doAnything() {
    		//业务逻辑处理
    	}
    	protected void doSomething() {
    		//业务逻辑处理
    	}
    	//重写钩子函数
    	@override
    	protected boolean isDo(){
    		return false;
    	}
    }
    public class ConcreteClass2 extends AbstractClass {
    	//实现基本方法
    	protected void doAnything() {
    		//业务逻辑处理
    	}
    	protected void doSomething() {
    		//业务逻辑处理
    	}
    	//重写钩子函数
    	@override
    	protected boolean isDo(){
    		return true;
    	}
    }
    
    
    




    我的视频课
    下面是我录制的一些视频课,欢迎大家围观~
    《设计模式修炼真经》
    设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结,代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。
    本套课程深入介绍了经典的23种设计模式,并加入了自己的感悟,希望大家能够彻底掌握设计模式,写出最好的代码,达到无招胜有招的境界,最终超越这23种设计模式。

    《彻底搞定JVM》
    JVM是Java中重要的也是较难理解的内容;
    面试者对JVM的了解程度某种程度上反映了面试者技术深度,所以JVM也是面试时经常考察的内容;
    本课程从JVM运行流程、数据运行时区域组成部分、类加载机制、垃圾回收机制、内存模型、常见面试题讲解等角度出发,帮你彻底搞定JVM,拿下心仪Offer;

    《Android性能优化参考》
    本课程包含了Android中的App启动优化、UI优化、内存优化、图片优化、耗电量等常见的性能优化场景,通过学习此课程,你将对整个Android性能优化体系有清晰的认识。

    性能优化作为Android高级开发的必备技能,也是大厂面试必考的题目,是体现一个人技术深度最好的试金石。

    《面试之排序算法》
    排序算法是我们面试被问到最多的基础算法,本课程详细介绍了七种排序算法,包括插入排序、选择排序、冒泡排序、谢尔排序、快速排序、堆积排序和二路并归排序。每种算法都详细介绍了核心思想、详细步骤、时间复杂度和代码实现,希望帮助大家深入理解排序算法,搞定面试!

    《Android HyBrid App开发实战》
    本课程为Android HyBrid App开发实战课程,由浅入深,从三种App的历史和特点开始,介绍了Android WebView的使用、Java和JS交互的原生方式、著名的WebView安全漏洞、JSBridge的原理和使用,最后通过一个网上商城的实战综合全部内容,让同学们掌握并深入理解Android HyBrid App开发。

    《AI导论》
    介绍人工智能AI的诞生历史和到现在为止的不同发展阶段;介绍了AI领域中常见的名词概念和其关系,包括机器学习、深度学习、神经网络结构搜索 NAS、生成对抗网络 GAN等;最后对AI发展做出展望。
    本课程属于导论课程,旨在帮助同学们从宏观层面把握AI,建立AI的知识体系。

    《Java注解精讲》
    本课程详细介绍了Java中的注解机制,包括注解的定义和分类,注解的使用和自定义,注解的源码和架构分析;
    本课程语言简单凝练,视频短小精悍,让你一次彻底搞懂Java注解!

    《Java反射精讲》
    反射是Java中重要的也是较难理解的内容;
    本课程从反射的定义、作用、原理和使用出发,全方位帮你彻底搞定反射;


    您的点赞是我前进的动力~

    在这里插入图片描述
    给作者买瓶咖啡提提神~


    更多相关内容
  • 第1节 关系模型的好坏 ER模型转换的关系是否...如果存在冗余,就需要对关系模式进行优化主要优化技术: 模式分解 (比如, ABCD 用 AB和BCD, 或者 ACD 和 ABD替代)。 如何正确地使用模式分解: 是否有必要分解一

    第1节 关系模型的好坏

    • ER模型转换的关系是否就是最优的关系?不一定。

      关系模型潜在的问题:

      • 添加异常
    • 修改异常

      • 删除异常
      • 数据冗余

    冗余

    • 当数据的某些部分能由其他部分推导出来,就意味着存在冗余
    • 冗余的存在是因为存在完整性约束

    如何解决冗余问题

    • 由于存在约束,特别是函数依赖,导致冗余的产生。
    • 如果存在冗余,就需要对关系模式进行优化。
      • 主要优化技术: 模式分解 (比如, ABCD 用 AB和BCD, 或者 ACD 和 ABD替代)。
    • 如何正确地使用模式分解:
      • 是否有必要分解一个模式?
      • 分解以后会不会出现什么问题?

    如何评价一个关系是好的还是坏的?

    • 坏关系到好关系

      • 对关系模式进行优化
      • 主要优化技术:模式分解(比如ABCD用AB和BCD,或者ACD和ABD代替)

    第2节 函数依赖的概念

    • 函数依赖概念
      • 函数依赖可形式化表示为X->Y, 其中X and Y是属性集
      • 例如:rating->hrly_wage, AB->C
      • 如果对于关系实例r中的任意一对元组t1和t2,有t1.X = t2.X逻辑蕴含t1.Y = t2.Y,那么函数依赖X->Y在关系r中成立
      • 即关系r中给定两个元组,如果X属性值相等则Y的值也必须相等(X和Y是属性集)
      • 如果对关系R中的每个实例r,都满足函数依赖,则该函数依赖在关系R上成立。
        • 函数依赖必须由应用的语义所决定。
        • 对于给定关系R的某实例r,我们能判断它是否违反了某个函数依赖。
        • 但是不能仅仅根据一个满足函数依赖的实例来断定该函数依赖在关系模式R上成立。
    • 函数依赖起到检测冗余是否存在的作用

    完全函数依赖

    在一张表中,若 X → Y X \rightarrow Y XY,且对于 X 的任何一个真子集(假如属性组 X 包含超过一个属性的话), X ′ → Y X' \rightarrow Y XY 不成立,那么我们称 Y 对于 X 完全函数依赖,记作 X → F Y X\mathop{\rightarrow}\limits ^F Y XFY

    例如:

    • 学号 → F \mathop{\rightarrow}\limits ^F F姓名
    • (学号,课名) → F \mathop{\rightarrow}\limits ^F F分数 (注:因为同一个的学号对应的分数不确定,同一个课名对应的分数也不确定)

    部分函数依赖

    假如 Y 函数依赖于 X,但同时 Y 并不完全函数依赖于 X,那么我们就称 Y 部分函数依赖于 X,记作 X → P Y X \mathop{\rightarrow}\limits ^P Y XPY

    例如:

    • (学号,课名) → P \mathop{\rightarrow}\limits ^P P姓名

    主属性

    包含在任意一个码中的属性称为主属性。

    非主属性

    不包含在任何一个码中的属性称为非主属性。

    第3节 范式和Armstrong公理

    范式

    如果一个关系满足一种范式(BCNF,3NF等),就能判断该关系模式是否避免了某类问题。这样就能知道该关系是否需要分解。

    • 任何符合BCNF的关系也符合 2NF

    第一范式(1NF)

    • 每个属性都是原子属性
    • 本质上所有关系都满足第一范式

    第二范式(2NF)

    • 任何满足第二范式的关系满足第一范式
    • 所有非主属性必须依赖于整个主码而不能依赖于主码的部分属性
    • 例如:关系模式 Inventory(part, warehouse, quantity,warehouse_address).
      假设 {part, warehouse}是主码. warehsouse_address 单独依赖于 warehouse -则违反了第二范式。 解决方法: 分解关系模式

    第三范式(3NF)

    • 任何符合BCNF的关系也符合 3NF
    • 符合3NF要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。
    • 有一些情况
      • BCNF 不能保持函数依赖,
      • 在更新上有效的检查函数依赖是否违背是非常重要的。
    • 解决方法: 定义一个弱的关系, 叫做第三范式 (3NF)
      • 允许存在一些冗余

      • 函数依赖是否保持可以在单独的关系上检查,而不需要进行连接计算.

      • 3NF一般是保持无损连接分解和保持函数依赖

    • R符合BCNF, 那么R符合3NF
    • 如果 R 符合 3NF, 可能会存在一定的冗余,它是分解和性能的一种折中
    • 将R分解为满足3NF的关系集合,是保持了无损连接分解和保持函数依赖的
    3NF分解
    • 显然, 分解为BCNF的无损连接分解的算法能够用来获取无损连接分解的3NF.
    • 为了保持函数依赖, 一个思想是:
      • 如果 X → Y 不保持, 增加关系XY.
      • 问题是XY可能会违背 3NF!
    • 细化: 不考虑 FDs F, 而是使用F的最小的函数依赖集.

    图片42

    3NF分解算法的其它例子

    图片43

    Boyce-Codd 范式(BCNF)

    • 对于 R 有函数依赖集 FDs F ,如果R符合BCNF 当且仅当每一个非平凡的 FD

      • X → A in F , X 是R的超键 (i.e., X → R in F+).

      • 对于 FD X → A 是平凡的,当且仅当 A ⊆ X.

    • 也就是说, R 符合BCNF 当且仅当非平凡的FDs 箭头左侧是键.
      BCNF:

    • R中没有数据能够使用FDs预测.

    • Why:

      • X是超键, 不会有两个元组的X值相同
    • 如果R只有两个属性, 那么它符合BCNF

    • 如果F只包括R中的属性:

      • R 符合BCNF 当且仅当每一个F中的函数依赖 X → Y (not F+!), X 是 R的超键, i.e., X → R is in F+ (not F!).
    BCNF的检测
    • 列出所有的非平凡函数依赖
    • 确认每一个函数依赖箭头左边的属性集是R的超键。
    • 注意:我们需要首先找出R的超键!

    例:Courses(course_num, dept_name, course_name, classroom, enrollment, student_name, address) 符合BCNF?
    FDs 包括:

    • course_num, dept_name → course_name

    • course_num, dept_name → classroom

    • course_num, dept_name → enrollment

    那么(course_num, dept_name)+?

    • {course_num, dept_name, course_name, classroom, enrollm ent}
      Therefore, the key is {course_num, dept_name, student_name}

    不符合BCNF

    BCNF范式分解
    • 当一个关系不符合BCNF: 那么分解它.
    • 假定关系R 包含属性A1 … An. R的分解会分解为两个或者多个关系:
      • 每个新的关系的属性为R属性的子集 (不会有属性不属于 R), 并且R 中的每一个属性至少会在一个新的关系中.
    • 考虑关系R 和函数依赖集 FDs F. 如果F中的函数依赖 X → A 违背 BCNF, 那么: 分解R 为R – A 和XA.
    • 重复这个思想,我们会得到一个符合BCNF的关系集合.
    • 保持无损连接分解。
    将关系模式R<U,F>分解为一个BCNF的基本步骤

    image-20200608143938557

    快速求候选码的方法

    首先对于给定的R(U)和函数依赖集F,可以将它的属性划分为4类:

    • L类,仅出现在F的函数依赖左部的属性。
    • R类,仅出现在F的函数依赖右部的属性。
    • N类,在F的函数依赖左部和右部均未出现的属性。
    • LR类,在F的函数依赖左部和右部两部均出现的属性。

    根据以下定理和推论来求解候选码。

    • 定理1:对于给定的关系模式R及其函数依赖集F,若X(X∈R)是L类属性,则X必为R的任一候选码的成员。
    • 推论1:对于给定的关系模式R及其函数依赖集F,若X(X∈R)是L类属性,且X+包含了R的全部属性,则X必为R的唯一候选码。
    • 定理2:对于给定的关系模式R及其函数依赖集F,若X(X∈R)是R类属性,则X不在任何候选码中。
    • 定理3:设有关系模式R及其函数依赖集F,如果X是R的N类属性,则X必包含在R的任一候选码中。
    • 推论2:对于给定的关系模式R及其函数依赖集F,如果X是R的N类和L类组成的属性集,且X+包含了R的有属性,则X是R的唯一候选码。

    例:

    如设有关系模式R(U),其函数依赖集为F,其中:U={A,B,C,D,E}, F={A→C,C→A,B→AC,D→AC} 求R的候选码。
    解:
    根据函数依赖可得:
    属性B、D为L类,E为N类,因此属性B、D、E必为候选码的成员,
    且此三个属性的闭包:B+=ABC,(BD)+=ABCD,(BDE)+=ABCDE,根据推论2可得BDE是R的唯一候选码。
    所以R的候选码为BDE。
    

    如果把例题中关系模式R(U)中的属性E去掉,那么再求R的候选码的话可以根据推论1得出BD为R的唯一候选码。

    快速求解方法适用于判断有属性是属于L类、N类或其中一种的情况下求解。如果有L类和N类的属性,则求解候选码速度非常快。

    简而言之:

    L、R、N、LR类。根据定理,L、N类必为侯选码之一,如果L+包含全部R,则L为唯一侯选。R类不在任何侯选码中。

    L+N类且(L+N)+包含所有R,则L+N为唯一侯选。(适于有L、N类至少一种的情况。)

    例题:
    设有关系模式R(A,B,C,D,E),其函数依赖集F={A→BC,CD→E,B→D,E→A},求R的所有候选码。
    解:
    (1)Fm={A→B, A→C,CD→E,B→D,E→A}
    (2)A,B,C,D,E五个属性在F中各个函数依赖的右边和左边都出现了,所以候选码中可能包含A,B,C,D,E。
    (3)A+=ABCDE,即A→U,所以A是一个候选码   B+,C+,D+→U,所以B,C,D不是候选码   E+=ABCDE,即E→U,所以也E是一个候选码
    (4)除去A,E两个候选码,在B,C,D中查找两个属性的候选码   (BC)+=ABCDE,即BC→U,所以BC是一个候选码   (BD)+=BD,即BC→U,所以BD不是一个候选码   (CD)+=ABCDE,即CD→U,所以CD是一个候选码
    候选码有:A,E,BC,CD
    

    BCNF 和 依赖保持

    • 分解得到的关系,符合BCNF,但可能不满足保持函数依赖.
    • 例子: 关系CSZ (city, street_name, zip_code) 函数依赖 FDs: CS → Z, Z → C
      (city, street_name) → zip_code
      zip_code → city
    • 要保持CS → Z,则不能分解, 但是CSZ 不符合BCNF.

    函数依赖理论:Armstrong公理

    从一个给定的函数依赖集推导出它所逻辑蕴含的所有函数依赖

    图片28

    图片29

    图片30

    第4节 函数依赖集

    4.1 函数依赖和键

    • 给定R(A,B,C)

      • A->ABC意味着A是一个键(码)
    • 通常,

      • X → R 意味着 X 是一个超键.
    • 键的约束

      • ssn → did

    图片31

    4.2 函数依赖集的闭包F+

    • 函数依赖集的闭包?由F逻辑蕴含的所有函数依赖的集合
    • 计算函数依赖集的闭包:

    图片32

    F+例子

    F = {A → B, B → C, C D → E }

    • Step 1: F中的每一个函数依赖, 使用自反律
      • 得到:CD → C; CD → D

      • 加到F上: F = {A → B, B → C, C D → E; CD → C; CD → D }

    • Step 2: F中的每一个函数依赖, 使用增补率
      • A → B 得到: A → AB; AB → B; AC → BC; AD→ BD; ABC →BC; ABD → BD; ACD →BCD
      • B → C 得到: AB → AC; BC → C; BD → CD; ABC → AC; ABD → ACD, etc.
    • Step 3: 使用传递率
    • 重复1~3步骤…

    可以看出计算F+代价太高.

    4.3 求最小依赖集

    关系模式R(U,F)中,R=ABCDEG F={BE→G,BD→G,CD→A,CE→G,CDE→AB,BC→A,B→D}

    1. 首先把右边的属性都变成单个属性

      函数依赖集F={BE→G,BD→G,CD→A,CE→G,CDE→A,CDE→B,BC→A,B→D}

    2. 对于函数依赖F中的每个函数X->A,设G=F-{X->A},如果A属于关于函数依赖集G的闭包,将X->A从F中删除,否则保留,然后得出新的F。

      BE+=BEDG,包含G,删除。

      BD+=BD,不包含G,保留。

      CD+=CD,不包含A,保留。

      CE+=CE,不包含G,保留。

      CDE+=CDEAGBA,包含A,删除。

      CDE+=CDEAG,不包含B,保留。

      BC+=BCDGA,包含A,删除。

      B+=B,不包含D,保留。

      得到新的F={BD→G,CD→A,CE→G,CDE→B,B→D}

    3. 对于F中每一个左端包含多个属性的X->A(即去掉各依赖左部多余的属性。一个一个地检查函数依赖左部非单个属性的依赖),选择X的每个子集Z,如果A属于Z的闭包,则用Z->A代替X->A。

      BD→G:B+=BDG,包含G,去掉;D+=D,不包含G,保留。

      CD→A:C+=C,不包含A,保留;D+=D,不包含A,保留。

      CE→G:C+=C,不包含G,保留;E+=E,不包含G,保留。

      CDE→B:C+=C,不包含B,保留;D+=DG,不包含B,保留;E+=E,不包含B,保留。

    最后得出关系模式R(U,F)的最小依赖集Fm={D→G,CD→A,CE→G,CDE→B,B→D}

    4.3 属性集闭包

    • (函数依赖集闭包的大小是(属性的)指数级的)
    • 很多时候, 我们仅仅是想判断一个 FD X →Y 是否在F的闭包中. 一个有效的方式是:
      • 计算属性X的闭包 (记为X+) :
        • X的闭包 就是由X在F上蕴含的所有属性的集合。
        • 计算属性的闭包仅仅需要一个线性的时间算法就够了.
      • F = {A → B, B → C, C D → E } A → E成立吗?

    属性集闭包的作用

    1. 测试超键
      • – 判断X是否是一个超键?只需要计算 X+, 检查 X+ 是否包括R的所有属性.
    2. 检测函数依赖
      • 判断X → Y 是否成立 (或者说, 是否在F+中), 只需要判断Y ⊆ X+.
      • 因此, 我们计算X+, 然后检测这个属性集闭包是否包括 Y.
      • 简单有用的方法
    3. 计算F的函数依赖集闭包

    图片33

    图片34

    图片35

    图片37

    第5节 模式分解的基本标准

    分解的问题

    • 模式分解可能存在三种问题:

      1. 一些查询可能会代价变高.
        e.g., Attishoo 挣了多少钱? (earn = W*H)
      2. 分解后,根据分解的实例, 我们可能不能重新构建分解前的实例!
      3. 检查某些依赖需要考虑分解后的多个关系.
    • 折中: 考虑这些问题 vs. 冗余.

    分解

    • 将分解符合3NF或更高的范式是一种很好的保证方法.
    • 所有分解应该是无损的! (Avoids Problem (2))

    无损连接分解

    • 将R 分解为 R1 和R2 ,如果是无损连接分解,那么应该满足:

    图片38

    例子(不是无损的)

    图片39

    例子(无损的)

    图片40

    保持函数依赖

    • 保持函数依赖的分解(直观上):
      • R 分解为X, Y 和Z, 函数依赖集FDs在X,Y,Z上成立,那么FDs也会在R上成立。

    分解后的函数依赖?

    • 函数依赖集的投影: R 分解为 X, … F 在X上的投影 (denoted FX ) 是如下的 FDs U → V in F+ (closure of F ) ,U, V 是X中的属性.

    保持函数依赖的分解

    • 将R分解为X和Y是保持函数依赖的,当且仅当 ( F X ∪ F Y ) + = F + (F_X \cup F_Y)^+ = F^+ (FXFY)+=F+
    • 注意是 F + F^+ F+,而不是 F F F
    • 保持函数依赖并不能保证保持无损连接分解
    • 反之亦然

    判断两个函数依赖集是否等价

    • 如果 F1+ = F2+, 那么F1和F2等价.
    • 例如, F1={A →B, A →C} 和 F2={A → BC}等价

    例子

    • F={ A → BC, B →C }. 判断 C →AB 是否在 F+?
    • Answer: 不在.
      Reason 1) C+=C, 不包括 AB.
      Reason 2) 反例,不存在 C → AB.

    BCNF和3NF的比较

    • 将一个关系分解为符合3NF的关系集合:
      • 分解是无损的
      • 分解是保持函数依赖的
    • 将一个关系分解为符合BCNF的关系集合:
      • 分解是无损的
      • 可能不保持函数依赖

    图片44

    设计目标

    • BCNF
    • 无损连接
    • 保持函数依赖

    如果不能得到这些

    • 函数依赖的保持
    • 使用3NF产生冗余

    Example

    图片45

    • R(A,B,F), F = {AC → E, B → F}.
      • Candidate key? AB
      • BCNF? No, because of B → F (B is not a superkey).
      • 3NF? No, because of B → F (F is not part of a candidate key).
    • R(D, C, H, G), F = {A → I, I → A}
      • Candidate key? DCHG
      • BCNF? Yes
      • 3NF? Yes

    图片46

    • R(A,B,C,D,E,F),F={A->C,C->A,B->AC,D->AC}
      • 找出R的键
      • 是否符合3NF,如果是,说明原因,如果否,分解。
    (1)R的候选码为BD
    (2)
    ①将F中的函数依赖都分解为右部为单属性的函数依赖.
    F={A→C,C→A,B→A,B→C,D→A,D→C,BD→A}
    ②去掉F中冗余的函数依赖.
    判断A→C是否冗余.
    设:G1={C→A,B→A,B→C,D→A,D→C,BD→A},得(A)G1+=A
    ∵C不属于(A)G1+   ∴ A→C不冗余
    判断C→A是否冗余.
    设:G2={A→C,B→A,B→C,D→A,D→C,BD→A},得(C)G2+=C
    ∵A不属于(C)G1+   ∴ C→A不冗余
    判断B→A是否冗余.
    设:G3={A→C,C→A,B→C,D→A,D→C,BD→A},得(B)G3+=BCA
    ∵A属于(B)G3+   ∴ B→A冗余
    判断B→C是否冗余.
    设:G4={A→C,C→A,D→A,D→C,BD→A},得(B)G4+=B
    ∵C不属于(B)G4+   ∴ B→C不冗余
    判断D→A是否冗余.
    设:G5={A→C,C→A,B→C,D→C,BD→A},得(D)G5+=DCA
    ∵A不属于(D)G5+   ∴ D→A冗余
    判断A→C是否冗余.
    设:G6={A→C,C→A,B→C,BD→A},得(D)G6+=D
    ∵C不属于(D)G6+   ∴ D→C不冗余
    判断BD→A是否冗余.
    设:G7={A→C,C→A,B→C,D→C},得(BD)G7+=BDCA
    ∵A不属于(BD)G7+   ∴ BD→A冗余
    F={A→C,C→A,B→C,D→C}
    ③由于各函数依赖左部都为单属性,故:
    Fm={A→C,C→A,B→C,D→C}
    (3)τ={AC,BC,DC,BD}
    
    • 解法一

    图片47

    • 解法二

    图片48

    展开全文
  • 无约束优化方法

    千次阅读 2021-05-11 21:06:28
    简要介绍无约束优化方法,详细介绍牛顿法、 梯度下降法、Hook-Jeeves 的理论推导和python实现

    无约束优化方法

    1. 简介

    无约束问题是指只有优化目标,而不存在约束条件的问题,用数学模型可表示为

    在这里插入图片描述

    2. 无约束优化方法

    无约束优化方法是通常是由给定的初始点出发,按一定的规则不断向最优解趋近,根据不同的趋近思想/规则,有如下的方法。下面介绍其中常见的三种方法。
    在这里插入图片描述

    2.1 牛顿法

    2.1.1 理论推导

    牛顿法基本思想是用 f(x) 在已知点 x0 处的二阶 Taylor 展开式来近似代替f(x) ,即
    在这里插入图片描述
    用 g(x) 的极小值点 x1 作为 f(x) 的近似极小值点,即对g(x)两边求导,代入 x1 后化简:
    在这里插入图片描述
    在这里插入图片描述
    以此类推,得到迭代规则:
    在这里插入图片描述

    2.1.2 求函数极值

    import sympy as sy
    
    def cal_dffi(f,x0,d):
        x = sy.symbols("x")
        f1 = sy.diff(f,x,d)
        y = f1.evalf(subs={x:x0})
        
        return y
    
    
    def Newton(x0, f, detal):
        
        while True:
            x1 = x0 - cal_dffi(f,x0,d=1)/cal_dffi(f,x0,d=2)
            print(x1)
            if abs(x1-x0) < detal:
                break
            else:
                x0 = x1
                
        return x1
    
    
    if __name__ == '__main__':
        #定义函数
        x = sy.symbols("x")#声明变量
        f =  (x-1)**3 #函数
        x0 = 0 #初始点
        detal = 1e-10#精度
        f.evalf(subs={x:4})
        x = Newton(x0, f, detal)
        print("解:",x)
        
    #输出:0.999999999941792
    

    2.2 梯度下降法

    2.2.1 理论推导

    梯度下降法也叫最速下降法,基本思想是往函数下降最快的方向进行搜索,函数某个方向上的变化率可以用函数导数进行表征,因此搜索方向就可以根据函数导数确定,即以 f(x) 在点 xk 方向导数最小的方向作为搜索方向:
    在这里插入图片描述
    梯度下降法的特点是会随着接近目标值,步长减小,下降速度减慢。

    2.2.2 求解二元方程极值

    # -*- coding: utf-8 -*-
    import sympy as sy
    
    def cal_dffi(f,a,b):
        #声明变量
        x1 = sy.symbols("x1")
        x2 = sy.symbols("x2")
        #求偏导
        f1 = sy.diff(f,x1)
        y1 = f1.evalf(subs={x1:a,x2:b})
        f2 = sy.diff(f,x2)
        y2 = f2.evalf(subs={x1:a,x2:b})
        
        return y1,y2
    
    
    def gd(a, b, f, alpha, detal):
        x1 = sy.symbols("x1")#声明变量
        x2 = sy.symbols("x2")
        y0 = f.evalf(subs={x1:a,x2:b})#计算函数值
        
        while True:
            
            detalx,detaly = cal_dffi(f,a,b)
            a = a - alpha*detalx
            b = b - alpha*detaly
            y1 = f.evalf(subs={x1:a,x2:b})#偏导
            if abs(y1-y0) < detal:#函数值
                break
            else:
                y0 = y1
        return a,b,y1
    
    
    if __name__ == '__main__':
        #定义函数
        x1 = sy.symbols("x1")#声明变量
        x2 = sy.symbols("x2")
        f =  x1**2 + 2*x2**2 - 4*x1 - 2*x1*x2 #函数
        
        a = 1 #初始点
        b = 1
        alpha = 0.01
        detal = 1e-10#精度
    
        a,b,y = gd(a, b, f, alpha,detal)
        print("x1,x2,f极小值分别为",a,b,y)
        
    

    2.3 Hook-Jeeves

    2.3.1 理论推导

    Hook-Jeeves方法是一种简单、容易实现的方法,该方法首先进行探测搜索,找到下降的有利方向,再进行模式搜索,往有利的方向加速。其计算步骤如下:
    在这里插入图片描述

    2.3.2 求函数极值

    import sympy as sy
    
    if __name__ == '__main__':
        #函数
        x = sy.symbols("x")#声明变量
        f =  2*x**2-x+1 #函数
        
        #步骤1
        x1 = 1
        d = 1
        e = 0.5#
        n = 10
        
        alpha = 0.001
        E = 1e-5
        
        y1 = x1
        k = 1
        j = 1
        
        #步骤2
        while d >= E:
            
            while j < n:#步骤2
                if f.evalf(subs={x:y1+d*e}) < f.evalf(subs={x:y1}):
                    y1 = y1 + d*e
                elif f.evalf(subs={x:y1-d*e}) < f.evalf(subs={x:y1}):
                    y1 = y1 - d * e
                j += 1
                
            if y1 < x1:#步骤3判断
                tem = x1#步骤4
                x1 = y1
                y1 = x1 + alpha*(x1-tem)
                k += 1
                j = 1
                
            else:#步骤5
                d = d/2
                y1 = x1
                k += 1
                j = 1
    #x:0.2492
    
    展开全文
  • 在main方法里面的测试demo,可以看到通过不同的type类型,可以实现不同的策略,这就是策略模式主要思想。 在Context里面定义了两种写法: 第一种是维护了一个strategies的Map容器。用这种方式就需要判断每种策略...

    有情怀,有干货,微信搜索【三太子敖丙】关注这个有一点点东西的程序员。

    本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

    最近有一个学妹在跟我沟通如何有效的去避免代码中一长串的if else判断或者switch条件判断?针对更多的回答就是合理的去使用设计来规避这个问题。

    在设计模式中,可以使用工厂模式或者策略模式来处理这类问题,之前已经分享了工厂模式,感兴趣的同学可以去复习一下。

    设计模式系列往期文章:

    那么工厂模式和策略模式有什么区别呢?

    • 工厂模式是属于创建型设计模式,主要用来针对不同类型创建不同的对象,达到解偶类对象。
    • 策略模式是属于行为型设计模式,主要是针对不同的策略做出对应行为,达到行为解偶

    本次就来具体聊聊策略模式它是如何做到行为解耦

    大纲

    定义

    什么是策略模式?它的原理实现是怎么样的?

    定义一系列算法,封装每个算法,并使他们可以互换,不同的策略可以让算法独立于使用它们的客户而变化。 以上定义来自设计模式之美

    感觉有点抽象?那就来看一张结构图吧

    • Strategy(抽象策略):抽象策略类,并且定义策略执行入口
    • ConcreteStrategy(具体策略):实现抽象策略,实现algorithm方法
    • Context(环境):运行特定的策略类。

    这么看结构其实还是不复杂的,而且跟状态模式类似。

    那么这个代码怎么实现?

    举个例子,汽车大家肯定都不陌生,愿大家早日完成汽车梦,汽车的不同档(concreteStrategy)就好比不同的策略,驾驶者选择几档则汽车按几档的速度前进,整个选择权在驾驶者(context)手中。

    public interface GearStrategy {
    
        // 定义策略执行方法
        void algorithm(String param);
    }
    

    首先还是先定义抽象策略

    这里是用接口的形式,还有一种方式可以用抽象方法abstract来写也是一样的。具体就看大家自己选择了。

    public abstract class GearStrategyAbstract {
     // 定义策略执行方法
     abstract void algorithm(String param);
    }
    
    public class GearStrategyOne implements GearStrategy {
    
        @Override
        public void algorithm(String param) {
            System.out.println("当前档位" + param);
        }
    }
    

    其次定义具体档位策略,实现algorithm方法。

    public class Context {
    		// 缓存所有的策略,当前是无状态的,可以共享策略类对象
        private static final Map<String, GearStrategy> strategies = new HashMap<>();
    
        // 第一种写法
        static {
            strategies.put("one", new GearStrategyOne());
        }
    
        public static GearStrategy getStrategy(String type) {
            if (type == null || type.isEmpty()) {
                throw new IllegalArgumentException("type should not be empty.");
            }
            return strategies.get(type);
        }
    
        // 第二种写法
        public static GearStrategy getStrategySecond(String type) {
            if (type == null || type.isEmpty()) {
                throw new IllegalArgumentException("type should not be empty.");
            }
            if (type.equals("one")) {
                return new GearStrategyOne();
            }
            return null;
        }
    
    
        public static void main(String[] args) {
            // 测试结果
            GearStrategy strategyOne = Context.getStrategy("one");
            strategyOne.algorithm("1档");
             // 结果:当前档位1档
            GearStrategy strategyTwo = Context.getStrategySecond("one");
            strategyTwo.algorithm("1档");
            // 结果:当前档位1档
        }
    
    }
    

    最后就是实现运行时环境(Context),你可以定义成StrategyFactory,但都是一个意思。

    在main方法里面的测试demo,可以看到通过不同的type类型,可以实现不同的策略,这就是策略模式主要思想。

    在Context里面定义了两种写法:

    • 第一种是维护了一个strategies的Map容器。用这种方式就需要判断每种策略是否可以共享使用,它只是作为算法的实现。
    • 第二种是直接通过有状态的类,每次根据类型new一个新的策略类对象。这个就需要根据实际业务场景去做的判断。

    框架的应用

    策略模式在框架中也在一个很常见的地方体现出来了,而且大家肯定都有使用过。

    那就是JDK中的线程池ThreadPoolExecutor

    首先都是类似于这样定义一个线程池,里面实现线程池的异常策略。

    这个线程池的异常策略就是用的策略模式的思想。

    在源码中有RejectedExecutionHandler这个抽象异常策略接口,同时它也有四种拒绝策略。关系图如下:

    这就是在框架中的体现了,根据自己的业务场景,合理的选择线程池的异常策略。

    业务改造举例

    在真实的业务场景中策略模式也还是应用很多的。

    在社交电商中分享商品是一个很重要的环节,假设现在要我们实现一个分享图片功能,比如当前有 单商品、多商品、下单、会场、邀请、小程序链接等等多种分享场景。

    针对上线这个流程图先用if else语句做一个普通业务代码判断,就像下面的这中方式:

    public class SingleItemShare {
        // 单商品
        public void algorithm(String param) {
            System.out.println("当前分享图片是" + param);
        }
    }
    public class MultiItemShare {
        // 多商品
        public void algorithm(String param) {
            System.out.println("当前分享图片是" + param);
        }
    }
    public class OrderItemShare {
        // 下单
        public void algorithm(String param) {
            System.out.println("当前分享图片是" + param);
        }
    }
    public class ShareFactory {
    
        public static void main(String[] args) throws Exception {
            Integer shareType = 1;
           // 测试业务逻辑
            if (shareType.equals(ShareType.SINGLE.getCode())) {
                SingleItemShare singleItemShare = new SingleItemShare();
                singleItemShare.algorithm("单商品");
            } else if (shareType.equals(ShareType.MULTI.getCode())) {
                MultiItemShare multiItemShare = new MultiItemShare();
                multiItemShare.algorithm("多商品");
            } else if (shareType.equals(ShareType.ORDER.getCode())) {
                OrderItemShare orderItemShare = new OrderItemShare();
                orderItemShare.algorithm("下单");
            } else {
                throw new Exception("未知分享类型");
            }
            // .....省略更多分享场景
        }
    
        enum ShareType {
            SINGLE(1, "单商品"),
            MULTI(2, "多商品"),
            ORDER(3, "下单");
            /**
             * 场景对应的编码
             */
            private Integer code;
            /**
             * 业务场景描述
             */
            private String desc;
            ShareType(Integer code, String desc) {
                this.code = code;
                this.desc = desc;
            }
            public Integer getCode() {
                return code;
            }
           // 省略 get set 方法
        }
    }
    

    这里大家可以看到每新加一种分享类型,就需要加一次if else 判断,当如果有十几种场景的时候那代码整体就会非常的长,看起来给人的感觉也不是很舒服。

    接下来就看看如何用策略模式进行重构:

    public interface ShareStrategy {
        // 定义分享策略执行方法
        void shareAlgorithm(String param);
    }
    
    public class OrderItemShare implements ShareStrategy {
        @Override
        public void shareAlgorithm(String param) {
            System.out.println("当前分享图片是" + param);
        }
    }
    
    // 省略 MultiItemShare以及SingleItemShare策略
    
    // 分享工厂
    public class ShareFactory {
    		// 定义策略枚举
        enum ShareType {
            SINGLE("single", "单商品"),
            MULTI("multi", "多商品"),
            ORDER("order", "下单");
            // 场景对应的编码
            private String code;
           
            // 业务场景描述
            private String desc;
            ShareType(String code, String desc) {
                this.code = code;
                this.desc = desc;
            }
            public String getCode() {
                return code;
            }
           // 省略 get set 方法
        }
    		// 定义策略map缓存
        private static final Map<String, ShareStrategy> shareStrategies = new       HashMap<>();
        static {
            shareStrategies.put("order", new OrderItemShare());
            shareStrategies.put("single", new SingleItemShare());
            shareStrategies.put("multi", new MultiItemShare());
        }
        // 获取指定策略
        public static ShareStrategy getShareStrategy(String type) {
            if (type == null || type.isEmpty()) {
                throw new IllegalArgumentException("type should not be empty.");
            }
            return shareStrategies.get(type);
        }
    	
        public static void main(String[] args) {
            // 测试demo
            String shareType = "order";
            ShareStrategy shareStrategy = ShareFactory.getShareStrategy(shareType);
            shareStrategy.shareAlgorithm("order");
            // 输出结果:当前分享图片是order
        }
    }
    
    

    这里策略模式就已经改造完了。在client请求端,根本看不到那么多的if else判断,只需要传入对应的策略方式即可,这里我们维护了一个策略缓存map,在直接调用的ShareFactory获取策略的时候就直接是从换种获取策略类对象。

    这就已经达到了行为解偶的思想。同时也避免了长串的if else 判断。

    优点:

    • 算法策略可以自由实现切换
    • 扩展性好,加一个策略,只需要增加一个类

    缺点:

    • 策略类数量多
    • 需要维护一个策略枚举,让别人知道你当前具有哪些策略

    总结

    以上就讲完了策略模式,整体看上去其实还是比较简单的,还是那句话学习设计模式我们还是要学习每种设计模式的思想,任何一种设计模式存在即合理。当然也不要因为设计模式而设计代码,那样反而得不偿失。


    敖丙把自己的面试文章整理成了一本电子书,共 1630页!

    干货满满,字字精髓。目录如下,还有我复习时总结的面试题以及简历模板,现在免费送给大家。

    链接:https://pan.baidu.com/s/1ZQEKJBgtYle3v-1LimcSwg 密码:wjk6

    我是敖丙,你知道的越多,你不知道的越多,感谢各位人才的:点赞收藏评论,我们下期见!


    文章持续更新,可以微信搜一搜「 三太子敖丙 」第一时间阅读,回复【资料】有我准备的一线大厂面试资料和简历模板,本文 GitHub https://github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。

    展开全文
  • 实体关系抽取任务方法及SOTA模型总结

    万次阅读 多人点赞 2020-05-31 21:02:08
    对于实体关系抽取任务,最容易想到的方法就是先抽取句子中的实体,然后在对实体对进行关系分类,从而找出spo三元组,这种思想被称作管道模型(Pipeline)。管道模型把实体关系抽取分成了两个子任务,实体识别和关系...
  • Java性能优化的七个方向

    千次阅读 多人点赞 2022-03-08 20:03:57
    本文对Java性能优化的7种技术手段进行了简单的介绍。
  • 在我的理解里,要实现计算机视觉必须有图像处理的帮助,而图像处理倚仗与模式识别的有效运用,而模式识别是人工智能领域的一个重要分支,人工智能与机器学习密不可分。纵观一切关系,发现计算机视觉的应用服务于机器...
  • 因此研究员又提出来更先进的方法,其中包括比较有名的Gap Statistics方法,Gap Statistics方法的优点是不需要肉眼判断,只需要找到最大的Gap Statistics所对应的K即可,因此该方法也适用于批量优化作业。 (3)...
  • 你不可不知的数学四大思想方法

    千次阅读 2021-01-17 13:46:48
    名师指导合肥一中 高级教师 杜明成数学在培养和提高考生的思维能力方面有着其他学科不可代替的独特作用,这是因为数学不仅是一种重要的“工具”和“方法”,而且是一种思维模式,这表现为数学思想.高考试题十分重视对...
  • 目录 文章目录目录一、前言二、简介1. 谁发明了设计模式?2. 我怎么学不会设计模式?...5月20日那天投身实战型设计模式打磨,通过模拟互联网业务开发实际需求作为学习场景,讲解设计模式。 全书共计22个真实业务场
  • 性能优化方法论建设

    千次阅读 2018-04-12 10:27:08
    计算机的核心就是由这五大部分构成,网络io的输入、输出主要是网卡、带宽等资源,这是已经确定了的,由计算机底层优化,能优化的空间不大(也可以通过改变tcp缓冲区的大小来特地优化某些场景的性能,这个以后再说)...
  • 图像模式识别的方法

    万次阅读 多人点赞 2015-07-05 11:53:22
    图像模式识别的方法很多,从图像模式识别提取的特征对象来看,图像识别方法可分为以下几种:基于形状特征的识别技术、基于色彩特征的识别技术以及基于纹理特征的识别技术。其中,基于形状特征的识别方法,其关键是...
  • 性能优化原则和优化模式

    千次阅读 2018-10-02 12:08:32
    一般而言,性能优化指降低响应时间和提高系统吞吐量两个方面,但在流量高峰时候,性能问题往往会表现为服务可用性下降,所以性能优化也可以包括提高服务可用性。在某些情况下,降低响应时间、提高系统吞吐量和提高...
  • OpenCV常见的优化方法和技巧总结

    万次阅读 多人点赞 2018-02-24 15:53:36
    OpenCV常见的优化方法和技巧总结 【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78540206 目录 OpenCV常见的优化方法和技巧总结 一、OpenCV常见的优化方法总结 1.1 cv::...
  • iOS之性能优化·UITableView深度优化

    万次阅读 2021-10-23 16:20:59
    UITableView 的优化主要从四个方面入手: 提前计算并缓存好高度(布局),因为 tableView:heightForRowAtIndexPath: 是调用最频繁的方法; 滑动时按需加载,防止卡顿。这个在大量图片展示,网络加载的时候很...
  • Unity大场景数据加载及优化方案

    万次阅读 多人点赞 2018-08-07 16:29:55
    前段时间,有几个虚拟仿真公司跟我请教关于大地形的加载优化问题,它们使用的引擎都是自己研发的,引擎对于开发者来说,大同小异,它们的基本构造是一样的,关键是在于解决问题的方法,正是基于这个前提写了这个课程...
  • java常用8种 设计模式

    千次阅读 2022-02-28 21:47:09
    文章目录前言一、设计模式需遵守:7大基本原则1.单一职责原则【单一职责原则注意事项和细节】2.接口隔离原则3.依赖倒置原则【依赖传递方式】【依赖倒置原则注意事项和细节】4.里式替换原则5.开放封闭原则6.迪米特...
  • 揭开TCP传输性能优化的秘密

    万次阅读 2022-01-29 18:25:11
    我做过效果最好的TCP优化可将吞吐提升10%~20%,性能衰减长尾消除,P99接近中位数,如何做的?把这个秘密作为新年礼物送给穿皮鞋的经理们。 一句话就能说清楚: 我用了2000多个(约数,大致就是这个意思)if分支区分...
  • 这个道理大家都懂,但一旦到了性能优化上,却往往因为缺乏理论依据而选择了错误的优化方向,陷入了盲猜的窘境。在衡量一项优化是否能达到目的之时,不能仅靠感觉,它同样有一系列的指标来衡量你的改进。如果在改动...
  • Oracle数据库SQL优化详解

    千次阅读 多人点赞 2022-01-07 16:53:15
    Oracle数据库SQL优化1. Oracle SQL优化概述2. Oracle SQL优化详解2.1 Oracle 查询阻塞2.2 Oracle 查询耗时 SQL2.3.Oracle 查看执行计划2.4.Oracle 查看收集统计信息2.5.Oracle 查询优化器 -- 改写查询语句2.6.Oracle...
  • 如何在写代码中找到乐趣呢,我觉得,最好的方式就是:使用设计模式优化自己的业务代码。今天跟大家聊聊日常工作中,我都使用过哪些设计模式。 工作中常用到哪些设计模式 1.策略模式 1.1 业务场景 假设有这样的业务...
  • 为节省时间,画了一个简化的UML类图,省略了类中变量和方法,仅展示类之间的关系。三层结构分别对应MVP三层: 到此,MVP从解释到应用都有了一个大概,最好的借鉴是汲取思想而又不拘泥于模式,改进与否都是服务于你...
  • Java-记一次if-else代码优化

    万次阅读 多人点赞 2019-01-30 20:34:14
    文章目录概述原工程缩影第一次优化 【使用多态代替判断条件】Step1: 定义一个抽象的父类 AbstractFlowInfoExecutor ,抽取公共属性和方法Step2: 子类重写父类的方法,实现自定义业务逻辑Step3: 改造Service层Step3:...
  • 图解Java设计模式(一)

    万人学习 2019-02-27 21:06:35
    行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式) 2) 学习目标:通过学习,学员能...
  • 设计模式面试题(设计模式速成版)

    千次阅读 多人点赞 2021-03-22 16:57:23
    说明 该文章适用于之前学习过设计模式,但是基本忘了。...设计模式:软件设计模式是对各种面向对象方法的一种总结。前辈们遇到了好多设计问题,然后利用面向对象解决了。然后他们把他们的解决方案汇总
  • 常用的几种设计模式详解

    千次阅读 2021-04-09 15:01:27
    设计模式的概述 设计模式分类 创建型模式 特点是将对象的创建与使用分离(解耦),有 单例、原型、工厂方法、抽象工厂、建造者等5种。 结构型模式 用于描述如何将类或对象按某种布局组成更大的结构,代理、...
  • 目录 一、概述 二、7个设计原则 1、单一职责原则 ( SRP ) 2、开闭原则 ( OCP ) 3、里氏替换原则 ( LSP ) ...4、依赖倒置原则 ( DIP ) ...2.工厂方法模式 3.抽象工厂模式 4.建造者模式 5.原型模...
  • 设计模式6大原则

    千次阅读 2021-07-09 08:54:32
    设计模式的目的 设计模式是为了让程序(软件),具有更好的: 1)代码可重用性(即:相同功能的代码,不用多次编写) 2)可读性(即:编程规范性,便于其他程序员的阅读和理解) 3)可扩展性(即:当需要增加新的功能时,非常的...
  • 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人...
  • 基于Matlab的遗传算法程序设计及优化问题求解

    万次阅读 多人点赞 2020-10-21 17:23:50
    在科学和生产实践中表现为在所有可能的解决方法中找出最符合该问题所要求的条件的解决方法即找出一个最优解. 这种算法是1960年由Holland提出来的其最初的目的是研究自然系统的自适应行为并设计具有自适应功能的软件...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 140,033
精华内容 56,013
热门标签
关键字:

关系模式优化主要思想及方法