java设计模式概览

设计模式概览

介绍:

模式:模式是一种概览,在一个良好的指导下有助于设计一个优良的方案,达到事半功倍的效果,而且会得到解决问题的最佳方法。
设计模式的出现让我们站在前人的肩膀上通过一些成熟的设计方案来指导新项目的开发合设计,以便开发出具有更好的灵活性合可扩展性,也更易于复用的软件系统、
设计模式是一套呗反复使用的,多数人知晓的,经过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,代码更容易被他人理解并提高代码的可靠性。设计模式是一种用于软件系统中不断重现的设计问题的解决方案进行文档化的技术,也是一种共享设计经验的技术。

面向对象=》功能模块(设计模式+算法(数据结构))=》框架(使用到多种设计模式)=》架构(服务器集群)
优化-》
重量级对象-》单例模式,防止过多的创建重量级对象
七大原则,23种设计模式。
目的:
编写软件过程中,程序员面临这来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好
(1)代码重用性(即:相同功能的代码,不用多次编写)
(2)可读性(可读性,即编程规范性,便于其他程序员的阅读和理解)
(3)可扩展性(即:当需要增加新的功能时,非常的方便,称为可维护性)
(4)可靠性(当需要增加新的功能后,对原来的功能没有影响)
(5)使程序程序高内聚,低耦合的特性

uml关系:

泛化关系:
实际上就是继承关系。是依赖关系的特例
extends
实线加三角符号表示

实现关系:
a实现b是依赖关系的特例
implements
虚线加三角符号表示

关联关系:
是类与类之间的联系
实线加箭头符号表示
person中有idcard 表示1-1也可以1-n爱好

聚合关系:
表示整体跟部分之间的关系,整体与部分可以分开,是关联关系的特例
一台电脑由键盘,显示器等组成。
空心菱形加实线表示。

组合关系:
也是整体与部分之间的关系。
但是不可分割
实线加黑心菱形组合

设计模式的基本要素:

1.模式名称
2.问题
3.解决方案
4效果

设计模式的分类

1.根据目的分类
设计模式根据目的(模式是用来做什么的)可分为创建型,结构型,和行为型3类。
(1),创建型模式主要用于创建对象,GoF提供了5种创建型模式,分别是工厂方法模式,抽象工厂模式,建造者模式,原型模式和单例模式。
(2)结构型模式主要用于处理类或对象的组合,GoF提供7种结构型模式,适配器模式。桥接模式,组合模式。装饰模式,外观模式,享元模式,代理模式。
(3)行为型模式主要用于描述或对象怎麽交互和怎么分配职责,GoF提供了11种行为型模式,责任链模式,命令模式,解释器模式,迭代器模式,中介者模式,备忘录模式,观察者模式,状态模式,策略模式,模板方法模式,访问者模式。
2.根据范围分类
设计模式根据范围分类(即模式主要用于处理类之间的关系还是处理对象之间的关系)可分为类模式和对象模式。
(1)类处理模式处理类和子类的关系,这些关系通过继承建立,在编译时即被确定下来,是一种静态关系。
(2对象模式处理对象间的关系,这些关系在运行时变化,更具动态性。

23种设计模式:

创建型:
(1)抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。
(2)建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的建造过程可以创建不同的表示。
(3)工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的示例化延迟到其子类
(4)原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
(5)单例模式:确保一个类只有一个实例,并提供一个全局的访问点来访问这个实例。
结构型:
(1)适配器模式:将一个类的接口转换成客户希望的另一个接口。适配器模式让那些接口不兼容的类可以一起工作。
(2)桥接模式:将抽象部分与它的实现部分解耦,使得两者能够独立变化
(3)组合模式:组合多个对象形成树形结构以表示具有整体跟部分的关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。
(4)装饰模式:动态地给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。
(5)外观模式:为子系统种一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易被使用。
(6)享元模式:运用共享技术有效地支持大量细粒度对象的复用。
(7)代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。
行为型:
(1)责任链模式:避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求,将接收请求的对象连接成一条链传递请求,直到有一个对象能够处理他为止。
(2)命令模式:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
(3)解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
(4)迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而不用暴露该对象的内部表示。
(5)中介者模式:定义一个对象来封装对象的交互。使对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
(6)备忘录模式:在不破坏封装的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
(7)观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发送改变时其相关依赖对象皆得到通知自动更新。
(8)状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
(9)策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。该模式让其算法可以独立于使用它的客户而变化。
(10)模板方法模式:定义一个操作中的算法框架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可定义该算法的某些特定步骤、
(11)访问者模式:表示一个作用于某些特定结构中的各个元素的操作。访问者模式可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

7大设计原则:

(1)单一职责原则:一个对象应该只包含单一的职责,并且该职责被完整地封装到一个类中。
(2)开闭原则:软件实体应对扩展开发,对修改关闭。
(3)里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象。
(4)里氏替换原则:高层模块不应该依赖底层模块,他们都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象
(5)接口隔离原则:客户端不应该依赖那些它不需要的接口。
(6)合成复用原则:优先使用对象组合,而不是通过继承来达到复用的目的
(7)迪米特法则:每一个软件单位对其他单位都只有最少的知识(也叫最少直到原则),而且局限于那些与本单位密切相关的软件单位。

单一职责原则:
对类来说的,即一个类应该只负责一项职责,如类A负责两个不同职责:职责1,职责2.
当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2

比如userDao操作user表同时又操作order表就违反了单一职责原则
应该分为userDao跟orderDao
一个表对应一个表,相应地封装一个DAO类。 对于DAO接口,必须由具体的类型定义。这样可以避免被错误地调用。
在DAO模式中,将对数据的持久化抽取到DAO层,暴露出Service层让程序员使用,这样,一方面避免了业务代码中混杂JDBC调用语句,使得业务落实实现更加清晰。
通常我们创建一个包,用于保存DAO接口,再创建一个包,用于保存DAO接口的实现类即可。
这样就低耦合了。

重要:
(在代码中应该尽量避免过多的if else)因为这样代码的耦合就很高了,优秀的代码宁愿用多个类来进行松耦合

单一职责原则注意事项和细节
1)降低类的复杂度,一个类只负责一项职责。
2)提高类的可读性,可维护性
3)降低变更引起的风险。
4)通常情况下,我们应该遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则,只有类中方法数量足够少,可以在方法级别保持单一职责原则。

接口隔离原则:
要把类实现接口,在最小的接口上。

依赖倒转原则:
1)高层模块不应该依赖低层模块,二者都应该依赖其抽象。
2)抽象不应该依赖细节,细节应该依赖抽象。
3)依赖倒转(倒置)的中心思想是面对接口编程
4)依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。
以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中抽象指的是接口或抽象类。细节就是具体的实现类。
5)使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务的任务交给他们的实现类去做。

类合类直接依赖的后果就是高度耦合。
三种方式:
1.通过参数传递
2.通过构造器实现依赖传递
3.通过set方法实现依赖传递。

依赖倒转的注意事项和细节:
1)低层模块尽量都要有抽象类或接口,或者两者都要,程序稳定性更好。
2)变量的声明类型尽量是抽象类或接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。‘
3)继承时遵循里氏替换原则。

什么叫倒转?一个对象不去依赖他的具体实现,而是反过来去依赖他的上层父类,或接口。
A类的上层最好有抽象类或者接口,
如果一个对象直接指向一个对象的实例,这个对象直接引用到了实际的内存地址,中间没有缓冲层,如果将来要对这个类进行功能的扩展,几乎是不可能
设计方案:如果一个对象obj指向了一个抽象类,A继承了B,B又是抽象类,B ovj=new A,多态,父类引用指向子类对象。
如果未来要增加功能,我们可以不去修改A类,在抽象类B类上增加一个方法,A类就会增加这个功能,obj是跟B类关联起来的。
让我们跟实际对象之间具有一个缓冲层。

实例:如果一个对象直接去依赖一个类,比如new persion,person.receive(new Email),如果将来要修改email,改为weixin几乎是不可能的。
但是如果email是一个抽象类或接口,那么 可以让微信或者邮箱实现这个接口,定义的参数是接口,那么就可以传过来邮箱或者微信,这样稳定性就得到了提高。
里氏替换原则:
oo中的继承性的思考和说明:
1)继承包含了这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和锲约,虽然它不强制要求所有的子类必须遵循这些锲约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
2)继承在给程序带来便利的同时,也带来了弊端,比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类的功能需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能可能产生故障。
3)如何正确使用继承?尽量遵循里氏替换原则。

**里氏替换原则提出的概念:**如果对每个类型T1的对象o1,都有类型为T2的对象o2,使得T1定义的所有程序p在所有对象o1都代换成o2时,程序p的行为没有发生变化,那么类型t2是类型t1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。

操作:在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。
事实上从开发经验来看,很少有类直接继承一个,如果有继承那么父类必定是抽象类。
并且子类不会去重写父类的方法。
如果你要重写父类的方法,那么你继承他干什么?继承让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题。
可以让A类和B类提升,让他们去继承一个更基础的类。

开闭原则:
1)开闭原则是编程中最基础,最重要的设计原则
2)一个软件实体如类,模块和函数应该对扩展开发,对修改关闭。用抽象构建框架,用实现扩展细节。
3)当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
4)编程中遵循其他原则,以及使用设计模式的目的就是遵循开闭原则。

扩展开放:对提供方
修改关闭:使用方

如果修改原有的类,如果原有的类还被其他地方使用可能回影响到其他地方。

在有不同功能的时候不应该用if,因为这意味着要修改提供方的代码,应该用抽象类。

迪米特法制:
1)一个对象应该对其他对象保持最少的了解。
2)类与类关系越密切,耦合度越大。
3)迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都应该将逻辑封装在类的内部。对外提供的public方法,不对外泄漏任何信息。
4)迪米特法则还有更简单的定义:只与直接朋友通信。
5)直接朋友:每个对象都会与其他对象耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友。耦合的方式很多
依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接朋友,而出现在局部变量中的类不是直接的朋友。
也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

往往是先有设计才有源码。
uml图是代码还没写之前程序员之间沟通程序的设计方案。
uml类图:
1)用于描述系统中的类(对象)本身的组成和类(对象)之间的各种静态关系
2)类之间的关系:依赖,泛化(继承),实现,关联,聚合与组合。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值