java几种常用设计模式Word文件下载.docx
《java几种常用设计模式Word文件下载.docx》由会员分享,可在线阅读,更多相关《java几种常用设计模式Word文件下载.docx(13页珍藏版)》请在冰点文库上搜索。
饿汉式:
/**
*单例模式之饿汉式:
----线程安全,效率低
*特点:
在类加载时就已经创建好对象
*@authorDarrenHo
*
*/
publicclassSingleton{
//将构造方法封装为私有化,指明仅在类内部使用
privateSingleton(){
}
//在内部产生本类的实例化对象,将其封装成privatestatic类型
PrivatestaticfinalSingletoninstance=newSingleton();
//通过静态方法获取instance对象
publicstaticSingletongetInstance(){
returninstance;
懒汉式:
*单利模式值懒汉式:
线程不安全,要运用同步锁
publicclassSingletonLazy{
privateSingletonLazy(){
privatestaticSingletonLazyinstance;
publicstaticSingletonLazygetInstance(){
if(instance==null){
synchronized(SingletonLazy.class){
if(instance==null)
instance=newSingletonLazy();
}
}
}
2.工厂设计模式
程序在接口和子类之间加入了一个过渡端(工厂类),通过此过渡端可以动态取得实现了共同接口的子类实例化对象。
一个对象相关的职责通常有三类:
对象本身所具有的职责、创建对象的职责和使用对象的职责。
对象本身的职责:
就是对象自身所具有的一些数据和方法,可通过一些公开的方法来实现它的职责。
对象的创建职责和使用职责(开发中要将两者分开,不能耦合在一个对象中,减少代码的维护工作)-----工厂模式的优点
在所有的工厂模式中,我们都强调一点:
两个类A和B之间的关系应该仅仅是A创建B或是A使用B,而不能两种关系都有。
在Java语言中,我们通常有以下几种创建对象的方式:
(1)
使用new关键字直接创建对象;
(2)
通过反射机制创建对象;
(3)
通过clone()方法创建对象;
(4)
通过工厂类创建对象。
工厂模式优点:
1.将对象的创建和使用分离,也使得系统更加符合“单一职责原则”,也有利于开闭原则,即有利于对功能的复用和系统的维护。
2.将对象的创建和使用分离还有一个好处:
防止用来实例化一个类的数据和代码在多个类中到处都是,可以将有关创建的代码搬移到一个工厂类中。
3.可以引入工厂类来封装对象的创建逻辑和客户代码的实例化/配置选项。
缺点:
工厂没有可以提供实例的逻辑,必须修改源代码
3.代理设计模式
指由一个代理类来操作被代理类,被代理类执行具体的业务操作,而代理类负责其他相关业务的处理。
比如生活中的通过代理访问网络,客户通过网络代理连接网络(具体业务),由代理服务器完成用户权限和访问限制等与上网相关的其他操作(相关业务)。
静态代理模式:
静态代理模式实现步骤:
1)创建一个接口
2)创建一个委托类/被代理类,该类实现以上的接口
3)创建一个代理类,该代理类也实现以上接口(重写此方法)
并且声明一接口类型的引用变量,然后在代理类的构造器中初始化
4)在应用时:
1.先创建委托类
2.再创建代理类并将委托类的对象传入代理类的构造器中;
3.最后调用代理类实现了接口的方法
动态代理模式:
动态代理类特点:
·
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件,无需程序员手工编写它的源代码。
即-----------------动态生成代理类。
动态代理类和委托类的关系是在程序运行时确定。
动态代理可以让系统能够根据实际需要来动态创建代理类,让同一个代理类能够代理多个不同的委托类而且可以代理不同的方法。
动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。
动态代理实现步骤
:
1.通过实现
InvocationHandler
接口创建自己的调用处理器;
2.通过为
Proxy
类指定
ClassLoader对象和一组
interface来创建动态代理类;
3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
--
--------Proxy.newInstance()
4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
注意:
Java语言实现动态代理时需要用到位于java.lang.reflect包中的一些类:
Proxy类和InvocationHandler接口提供了生成动态代理类的能力。
Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现
(1)Proxy类
Proxy类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下:
1.publicstaticClass<
?
>
getProxyClass(ClassLoaderloader,Class<
...interfaces):
该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组
2.publicstaticObjectnewProxyInstance(ClassLoaderloader,Class<
[]interfaces,InvocationHandlerh):
该方法用于返回一个动态创建的代理类的实例
该方法返回实现了被代理类所实现的所有接口的Object对象,即动态代理,需要强制转型
参数loader表示代理类的类加载器---->
指定代理对象由哪一个类加载器负责加载
参数interfaces表示代理类所要实现的接口列表,这些接口被代理类已实现---》指明代理对象的类型----委托类.getInterfaces()获取
参数h表示所指派的调用处理程序类-----》代理类与处理类相关联
当一个代理实例中的业务方法被调用时将自动调用处理类中的invoke()方法。
handler:
调用处理器的对象,用于真正调用处理程序-----当调用代理对象中的方法时,转调处理器的对象的invoke()方法
(2)InvocationHandler接口
InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。
在该接口中声明了如下方法:
publicObjectinvoke(Objectproxy,Methodmethod,Object[]args):
该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。
动态代理类需要在运行时指定委托类所实现了所有接口,当
在调用动态代理对象的业务方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。
Objectproxy表示动态代理类的实例
Methodmethod表示代理类中正在调用的方法------每次只能是一个方法的方法对象
Object[]args表示调用方法的参数数组
动态代理对象调用业务方法----->
调用请求---自动转发-----处理类对象的invoke()-----实际调用委托类中的方法
提示:
若处理类对象的invoke()中,method.invoke(obj,args)的obj指定为代理类对象,则陷入死循环
method.invoke(obj,arg)中:
obj应指定为委托类对象,
是该方法对象所在的类对象实例;
表示调用那个对象的方法
实现invoke()方法,实现对请求的统一处理,实际调用在委托类中定义的方法
4、观察者设计模式
Observer模式是一种常用的设计模式,尤其是在界面设计中被广泛应用。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。
体现的设计原则是:
为了交互对象之间的松耦合设计而努力。
Observer模式的优点:
1、解除了观察者和目标之间的耦合关系。
目标不需要知道它的观察者的任何信息。
2、目标只是允许观察者订阅事件。
当目标产生一个事件时,它简单地将事件传给每一个观察者。
3、观察者模式实现了动态联动
所谓联动,就是做一个操作会引起其它相关的操作。
由于观察者模式对观察者注册实行管理,那就可以在运行期间,通过动态的控制注册的观察者,来控制某个动作的联动范围,从而实现动态联动。
4、观察者模式支持广播通信
由于目标发送通知给观察者是面向所有注册的观察者,所以每次目标通知的信息就要对所有注册的观察者进行广播。
当然,也可以通过在目标上添加新的功能来限制广播的范围。
1、观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个主题对象。
2、通过1中,一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动更新。
3、适用场景
(1)当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
(2)一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
观察者模式的组成
抽象主题角色:
把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。
抽象主题提供一个接口,可以增加和删除观察者角色。
一般用一个抽象类和接口来实现。
抽象观察者角色:
为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
具体主题角色:
实现抽象主题角色接口,在具体主题内部状态改变时,给所有登记过的观察者发出通知。
具体主题角色通常用一个子类实现。
具体观察者角色:
该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
通常用一个子类实现。
如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
观察者模式的类图
//抽象观察者角色
publicinterfaceWatcher
{
publicvoidupdate(Stringstr);
//抽象主题角色,watched:
被观察
publicinterfaceWatched
publicvoidaddWatcher(Watcherwatcher);
publicvoidremoveWatcher(Watcherwatcher);
publicvoidnotifyWatchers(Stringstr);
//具体观察者:
publicclassConcreteWatcherimplementsWatcher
@Override
publicvoidupdate(Stringstr)
{
System.out.println(str);
}
//具体主题角色
publicclassConcreteWatchedimplementsWatched
//存放观察者
privateList<
Watcher>
list=newArrayList<
();
publicvoidaddWatcher(Watcherwatcher)
list.add(watcher);
publicvoidremoveWatcher(Watcherwatcher)
list.remove(watcher);
publicvoidnotifyWatchers(Stringstr)
//自动调用实际上是主题进行调用的
for(Watcherwatcher:
list)
{
watcher.update(str);
}
思考观察者模式
1:
观察者模式的本质
观察者模式的本质:
触发联动。
当修改目标对象的状态的时候,就会触发相应的通知,然后会循环调用所有注册的观察者对象的相应方法,其实就相当于联动调用这些观察者的方法。
而且这个联动还是动态的,可以通过注册和取消注册来控制观察者,因而可以在程序运行期间,通过动态的控制观察者,来变相的实现添加和删除某些功能处理,这些功能就是观察者在update的时候执行的功能。
同时目标对象和观察者对象的解耦,又保证了无论观察者发生怎样的变化,目标对象总是能够正确地联动过来。
理解这个本质对我们非常有用,对于我们识别和使用观察者模式有非常重要的意义,尤其是在变形使用的时候,万变不离其宗。
2:
何时选用观察者模式
建议在如下情况中,选用观察者模式:
当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化,那么就可以选用观察者模式,将这两者封装成观察者和目标对象,当目标对象变化的时候,依赖于它的观察者对象也会发生相应的变化。
这样就把抽象模型的这两个方面分离开了,使得它们可以独立的改变和复用。
如果在更改一个对象的时候,需要同时连带改变其它的对象,而且不知道究竟应该有多少对象需要被连带改变,这种情况可以选用观察者模式,被更改的那一个对象很明显就相当于是目标对象,而需要连带修改的多个其它对象,就作为多个观察者对象了。
当一个对象必须通知其它的对象,但是你又希望这个对象和其它被它通知的对象是松散耦合的,也就是说这个对象其实不想知道具体被通知的对象,这种情况可以选用观察者模式,这个对象就相当于是目标对象,而被它通知的对象就是观察者对象了。
缺省适配模式
属于结构型模式,其主要作用是将一个类的接口转换成客户希望的另外一个接口。
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
缺省适配模式为一个接口提供缺省实现(abstractclassimplementinterface---此处接口的缺省实现为抽象类),这样的类型可以从这个缺省实现进行扩展,而不必从原有接口进行扩展。
1、什么时候适用?
当原接口中定义的方法太多,而其中大部分又不被需要时,这种模式非常实用。
由缺省适配器类(一般是AbstractClass)直接实现接口(Interface),并为所有方法提供缺省的空实现。
用户类就只需要继承适配器类,只实现需要的方法。
1.InterfaceA:
目标接口。
可能定义有很多方法,但这些方法不一定全都被用户类所需要。
2.AbstractClassB:
缺省适配模式的核心。
它实现InterfaceA接口,为所有方法提供空的实现(也就是{}的空实现)。
3.ClassBImplFun1:
用户类,它需要实现InterfaceA接口。
但因为InterfaceA方法众多,而ClassBImplFun1中对其中一两个方法(比如这里的Fun1())感兴趣。
如果直接实现InterfaceA,就需要提供众多的空方法。
所以它继承AbstractClassB,只需要重写它感兴趣的方法即可。
既实现了InterfaceA接口,又省去了定义空方法的麻烦。