设计模式总结

设计模式
创建型模式:帮助我们创建对象的。
*单例模式:只涉及到一个类的对象创建。保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
java.lang.Runtime
Runtime类封装了Java运行时的环境。每一个java程序实际上都是启动了一个JVM进程,那么每个JVM进程都是对应这一个Runtime实例,此实例是由JVM为其实例化的。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
由于Java是单进程的,所以,在一个JVM中,Runtime的实例应该只有一个。所以应该使用单例来实现。
public class Runtime {
private static Runtime currentRuntime = new Runtime();

public static Runtime getRuntime() {
    return currentRuntime;
}

private Runtime() {}

}
以上代码为JDK中Runtime类的部分实现,可以看到,这其实是饿汉式单例模式。在该类第一次被classloader加载的时候,这个实例就被创建出来了。
一般不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过getRuntime方法获取当前Runtime运行时对象的引用。

**饿汉式(线程安全,调用效率高。但是,不能延时加载。)
私有化静态属性(类加载时就创建对象)、私有化构造器、公共的方法
**懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
私有化静态属性(只是声明而不去初始化对象)、私有化构造器、公有化方法(只在第一次调用时初始化对象)
**通过反射的方式直接调用私有构造器
解决:加抛出异常代码防止反射多次调用创建多个对象。通过在私有构造器中手动抛出异常,避免通过反射创建多个单例对象!防止通过反射来调用这个!即多次调用的时候抛出异常
**通过反序列化的方式构造多个对象
可以通过定义readResolve()防止获得不同对象。反序列化时,如果对象所在类定义了readResolve(),(实际是一种回调),定义返回哪个对象。反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
**双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用) 对应于懒汉式!!!
私有化静态属性(只是声明而不去初始化对象)、私有化构造器、公有化方法(只在第一次调用时初始化对象)只不过把sychronized的位置从方法上移到了方法内部
**静态内部类式(线程安全,调用效率高。 但是,可以延时加载) *********** 》 懒汉式
静态内部类(第一次加载静态内部类时并不会去创建对象,而是调用方法后才会创建
)中定义静态属性,私有化static final静态属性、私有化构造方法、公有化方法
**枚举式(线程安全,调用效率高,不能延时加载。并且可以天然的防止反射和反序列 化漏洞!) ******** 》 饿汉式
定义一个枚举的元素,它就代表了单例的一个实例.这个枚举元素,本身就是单例对象!单例可以有自己的操作.添加自己需要的操作!

*工厂模式:实现了创建者和调用者的分离。
**简单工厂模式(静态工厂模式)
虽然某种程度不符合设计原则,但实际使用最多。
(对于增加新产品无能为力!不修改代码的话,是无法扩展的。)
简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法, 写一个方法通过接收的参数的不同来返回不同的对象实例。用来生产同一等级结构中的任意产品。
**工厂方法模式
不修改已有类的前提下,通过增加新的工厂类实现扩展。
创建一个工厂接口,为每一个类别都创建一个类别工厂实现工厂接口在里面实现方法用于创建对应的类别的对象用来生产同一等级结构中的固定产品。
**抽象工厂模式
不可以增加产品,可以增加产品族!
创建一个工厂接口,为每一种产品族创建一个族工厂实现工厂接口实现创建的方法返回对应的创建对象。用来生产不同产品族的全部产品。
JDBC中Connection对象的获取
Hibernate中SessionFactory创建Session
spring中IOC容器创建管理bean对象

*建造者模式:分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。
由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象; 相同的构建器,不同的装配顺序也可以做出不同的对象。
StringBuilder类的append方法
SQL中的PreparedStatement

原型模式:通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
Cloneable接口和clone方法
Prototype模式中实现起来最困难的地方就是内存复制操作,所幸在Java中提供了 clone()方法替我们做了绝大部分事情。
*
浅克隆存在的问题

  • – 被复制的对象的所有变量都含有与原来的对象相同的值,
  • 而所有的对其他对象的引用都仍然指向原来的对象。
  • 深克隆如何实现?
  • – 深克隆把引用的变量指向复制过的新对象,而不是原有的被引用的对象。
  • – 深克隆:让已实现Clonable接口的类中的属性也实现Clonable接口
  • – 基本数据类型能够自动实现深度克隆(值的复制)
  • – 有时候增加克隆的代码比较麻烦!
  • – 可以利用序列化和反序列化实现深克隆!
    让类别实现可克隆接口,重写clone()方法,实际克隆的时候我们直接调用clone()方法完成
    原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone 的方法创建一个对象,然后由工厂方法提供给调用者。
  • • spring中bean的创建实际就是两种:单例模式和原型模式。(当然,原型模式需要和工厂模式搭配起来)

*结构型模型:关注对象和类的组织
*代理模式 :为真实对象提供一个代理,从而控制对真实对象的访问
**静态代理:真实角色实现抽象角色、代理角色实现抽象角色将真实角色作为属性通过构造方法传入真实角色,重写方法中用调用真实角色的方法
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。
**动态代理:
• JDK自带的动态代理

  • java.lang.reflect.Proxy作用:动态生成代理类和对象
  • java.lang.reflect.InvocationHandler(处理器接口):
  • 可以通过invoke方法实现对真实角色的代理访问;
  • 每次通过Proxy生成代理类对象时都要指定对应的处理器对象
  • java.lang.reflect.InvocationHandler接口的定义如下:
  • //Object proxy:被代理的对象
  • //Method method:要调用的方法
  • //Object[] args:方法调用时所需要参数
  • public interface InvocationHandler {
  • public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    
  • }
  • java.lang.reflect.Proxy类的定义如下:
  • //CLassLoader loader:类的加载器
  • //Class<?> interfaces:得到全部的接口
  • //InvocationHandler h:得到InvocationHandler接口的子类的实例
  • public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
    **
  • 代理类的内容不需要自己定义了,交给工具来生成代理类的内容。定义处理器的接口。

抽象角色
写自己的XXhandler方法,实现InvocationHandler类,实现invoke方法。
将真实角色作为属性,通过构造器传入真实角色。在invoke()方法中书写自己的处理逻辑,通过调用invoke()方法来使真实对象工作。
创建真实对象、创建XXhandler、创建代理对象(通过newProxyInstance
,三个参数分别表示为)
*动态代理实现步骤

  • 具体步骤是:
  • a. 实现InvocationHandler接口创建自己的调用处理器
  • b. 给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
  • c. 以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
  • d. 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象

struts2中拦截器的实现
Hibernate中延时加载的实现

  • – mybatis中实现拦截器插件
    spring中AOP的实现

*适配器模式:使原本由于接口不兼容不能一起工作的类可以一起工作
//类适配器(适配器继承需要适配的类在实现的方法中调用父类的操作方法、实现目标接口实现方法)
//对象适配器(适配器实现目标接口重写方法中调用需要适配类的操作方法、将需要适配的类作为属性通过构造器传递需要适配的类)
java.io.InputStreamReader(InputStream)

  • java.io.OutputStreamWriter(OutputStream

*桥接模式:处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联
桥接模式:电脑类中将品牌类作为属性通过构造器传递品牌类,方法中调用品牌类的销售方法、具体的类型电脑类继承电脑类重写构造方法
(将品牌类作为属性通过构造器传递品牌类),重写销售方法中调用父类的方法加上自己的业务
JDBC驱动程序

  • 组合模式:将对象组合成树状结构以表示”部分和整体“层次结构,使得客户可以统一的调用叶子对象和容器对象
    //叶子节点实现抽象组件重写杀毒方法、容器节点实现抽象组件构建列表进行增删改查并且重写递归的杀毒方法(调用叶子节点的杀毒方法)【通过抽象组件来调用叶子节点,因为可能是叶子可能是容器】
    Junit单元测试框架

*装饰模式:动态地给一个对象添加额外的功能,比继承灵活
具体构件实现抽象构件重写移动方法、装饰角色实现抽象构件将抽象构件作为属性通过构造方法传递并且调用抽象的移动方法、
具体装饰角色继承装饰角色重写构造方法调用父类的构造方法(实现抽象构件将抽象构件作为属性通过构造方法传递)、添加自己的方法、重写移动方法
IO中输入流和输出流的设计
Struts2中,request,response,session对象的处理

*外观模式:为子系统提供统一的调用接口,使得子系统更加容易使用
使用一个类把其他类的并列功能全部实现
JDBC封装后的,commons提供的DBUtils类,Hibernate提供的工具类、Spring JDBC工具类等

  • 享元模式:运用共享技术有效的实现管理大量细粒度对象,节省内存
    //抽象享元类、具体享元类实现抽象享元类,为内部状态提供成员变量进行存储,通过构造方法传递内部状态,把外部状态当做属性传进来放在具体的实现方法中
    //非共享享元类 坐标类–外部状态单独作为非共享享元类,有自己的属性构造器
    //享元工厂类 构建容器,放入抽象享元类,写一个方法用来制造抽象享元类【如果有这个颜色的就直接返回,没有才创建】
    //创建棋子时只需填入颜色,之后调用具体的方法设置它的方位
    享元模式由于其共享的特性,可以在任何“池”中操作,比如:线程池、数据库连接池。
    String类的设计也是享元模式

行为型模式:关注系统中对象之间的相互交互,研究系统在运行时对象之间的相互通信和协作,进一步明确对象的职责
创建型模式:关注对象的创建过程。
结构型模式:关注对象和类的组织。
责任链模式:避免请求发送者和接受者耦合,让多个对象都有可能接收请求,将这些对象连成一条链,并且沿着这条链传递请求,直到有对象处理为止。将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。
//请求类
//抽象领导类(属性:姓名、下一个领导 方法:设定责任链上的后继对象、处理请求的核心的业务方法)
//具体领导类继承抽象领导类(实现请求方法【自己处理请求或者调用自己的后继对象来处理请求】)
Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch.
Servlet开发中,过滤器的链式处理
Struts2中,拦截器的调用也是典型的责任链模式

命令模式:将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;使得请求调用者和请求接受者解耦。对请求排队或者记录请求日志,以及支持可撤销的操作。也称之为:动作Action模式、事务transaction模式。
Command 抽象命令类,定义执行方法
ConcreteCommand 具体命令类 实现抽象命令类,实现执行方法。将接收者(真正的命令执行者)作为属性,通过构造器传参传入接收者。
并在执行方法中,调用接收者的动作方法。
Invoker 调用者/请求者 持有对命令的引用,将命令类作为属性,通过构造器传参传入命令类。在业务方法中调用命令类的执行方法。
请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联。在程序运行时,将调用命令对象的execute(),间接调用接收者的相关操作。
Receiver 接收者 真正的命令执行者,定义动作方法。
接收者执行与请求相关的操作,具体实现对请求的业务处理。
未抽象前,实际执行操作内容的对象。

Client客户类
在客户类中需要创建具体命令类对象、调用者对象,在创建具体命令对象时指定对应的接收者,在创建调用者对象时执行对应的命令对象。
发送者和接收者之间没有直接关系,都通过命令对象间接调用。避免了调用者与接受者直接起作用。
Struts2中,action的整个调用过程中就有命令模式。

解释器模式 interpreter
EL表达式式的处理
正则表达式解释器
SQL语法的解释器

迭代器模式:提供一种可以遍历聚合对象的方式。又称为:游标cursor模式
聚合对象:存储数据
迭代器:遍历数据

  • 迭代抽象类:接口。用于定义得到开始对象、得到下一个对象、判断是否存在下一个对象、判断是否是开头、是否到达结尾、获取当前对象等抽象方法,统一接口
  • 具体迭代类:继承迭代抽象类。定义游标、定义聚集类作为属性,通过构造函数传递聚集类。实现上述各种方法。
  • 聚集抽象类:定义创建迭代的方法。
  • 具体聚集类:继承聚集抽象类。定义容器属性,定义增删改查对象到列表中的方法、实现创建迭代的方法【从而与迭代联系起来!】
    JDK内置的迭代器(List/Set),实现了iterator接口

中介者模式:解耦多个同事对象之间的交互关系。每个对象都持有中介者对象的引用,只跟中介者对象打交道。我们通过中介者对象统一管理这些交互关系
抽象中介类:接口,方法:建立关联、发送命令

  • 具体中介类:实现抽象接口类,实现各个方法。创建一个map,用于存储有多少个部门。建立关联就是把这个放进map中,发送命令就是调用某个部门的对外方法。
  • 抽象部门类:接口,方法:自己部门的动作、它向外提供的动作
  • 具体部门类:实现抽象部门类,实现各个方法。每个部门都持有一个对总经理的引用,把中介类作为属性,通过构造器传递参数进来中介类【同时调用中介类的关联方法与本部门进行关联】。
  • 在部门这个设置中介的引用,同时在中介这里注册,让他们互相可以找到。并且可以在实现方法中使用这个中介去调用别的部门的对外方法!
    MVC模式(其中的C,控制器就是一个中介者对象。M和V都和他打交道)

备忘录模式:就是保存某个对象内部状态的拷贝,这样以后就可以将该对象恢复到原先的状态。

  • 源发器类 Originator 保存对象内部的状态。定义类、构造器、get/set
  • 源发器类中还需要加两个内容:进行备忘操作,并返回备忘录对象【创建备忘录对象,参数是this】;进行数据恢复,恢复成指定备忘录对象的值【参数是备忘器类】
  • 备忘录类 Memento 保存对象内部状态的拷贝。定义类、构造器【参数是源发器类】、get/set
  • 负责人类 CareTaker 存储备忘录的。管理备忘录对象,把备忘录类作为一个属性,通过set扥方法传递参数进来
    *careTaker.setMemento(emp.memento());//备忘
    *emp.recovery(careTaker.getMemento());//恢复
    要设置多个备忘点,通过容器来做
    普通软件中的,撤销操作
    数据库软件中的,事务管理中的,回滚操作

观察者模式:观察者模式主要用于1:N的通知。当一个对象(目标对象Subject或Objservable)的状态变化时,他需要及时告知一系列对象(观察者对象,Observer),令他们做出响应

  • 通知观察者的方式:
  • 每次都会把通知以广播方式发送给所有观察者,所有观察者只能被动接收。
  • 观察者只要直到有情况即可。至于什么时候获取内容,获取什么内容,都可以自主决定。
    抽象观察者类 定义更新方法方法参数为目标类
    观察者类 实现抽象观察者类,实现更新方法【调用目标类的获取状态方法】。定义状态参数、定义获取状态和设置状态。
    抽象目标类 把订阅这个主题的所有观察者都放到这里,通知所有的观察者
    定义观察者列表参数、定义注册观察者和移除观察者的方法、定义通知所有观察者的方法【即循环调用所有观察者的更新方法】
    目标类 继承抽象目标类。定义状态参数、定义获取状态和设置状态【调用通知所有观察者的方法】目标对象值发生了变化,请通知所有的观察者
    //创建目标对象
    //创建多个观察者
    //将多个观察者添加到目标对象的观察者队伍中
    //改变目标对象的状态
    //看看观察者的状态有没有发生变化吧
    JAVASE提供了java.util.Observable和java.util.Observer来实现观察者模式
  • 目标类继承Observable。 定义状态、定义获取状态和设置状态方法。定义设置的方法【目标对象状态发生了更改、表示目标对象已经做了更改、通知所有的观察者】
  • 观察者类实现Observer。定义状态、定义获取状态和设置状态方法。定义更新方法,调用Observable的获取参数方法。
    Servlet中,监听器的实现

状态模式:用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题
Context环境类 状态类作为属性,通过set方法传递参数的形式传入状态类。

  • 并且在设置状态的方法中调用状态类的handle方法来切换状态。
  • 环境类中维护一个State对象,他是定义了当前的状态。维持不同状态之间的切换。持有不同的状态作为引用
  • State抽象状态类 定义了handle方法
  • ConcreteState具体状态类 实现了抽象状态类,重写了handle方法。
  • 每一个类封装了一个状态对应的行为
    线程对象各状态之间的切换

策略模式:策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法。并且由客户端决定调用哪个算法。
抽象策略类 定义计算价格的方法。

  • 具体策略类,实现策略算法类,实现计算价格的方法。每一个算法对应一个独立的算法类,实现了同一个接口,对外统一提供服务
  • 上下文类,用来管理算法。这里设置算法的引用。上下文类,指向了具体的算法的引用,替换引用即可。负责与具体的策略类交互
  • 将策略类作为一个属性,通过构造方法传递参数的形式传入策略类。并且在输出价格方法中调用策略类的计算价格的方法。
  • Spring框架中,Resource接口,资源访问策略
  • javax.servlet.http.HttpServlet#service()

模板方法模式:处理某个流程的代码已经都具备,但是其中某个节点的代码暂时不能确定。

  • 因此,我们采用工厂方法模式,将这个节点的代码实现转移给子类完成。
  • 即:处理步骤父类中定义好,具体实现延迟到子类中定义
    抽象模板方法:定义普通方法和抽象的业务方法,定义处理方法用于调用普通方法和业务方法实现完整的流程。
  • 具体业务子类:实现抽象模板方法,实现具体的业务类。更多的是采用匿名内部类的形式来实现这个业务方法,就不需要再额外定义这个子类了。

子类不能调用父类,而通过父类调用子类。这些调用步骤已经在父类中写好了,完全由父类控制整个过程。
数据库访问的封装
Junit单元测试
servlet中关于doGet/doPost方法调用
Hibernate中模板程序
spring中JDBCTemplate、HibernateTemplate等。

访问者模式:表示一个作用于某对象结构中的各元素额操作,它使得用户可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值