菜鸟版JAVA设计模式—适配器模式,装饰模式,代理模式异同

节前把3个设计模式的学习心得分享了一下,分别是适配器模式,装饰模式,代理模式。

但是似乎越写越有些迷糊,这三种模式都有着一些大同小异的地方,总是有些搞不清。

今天再重新学习下,把学习心得分享给大家一下。这次是结合的我工作中的实际项目。

设计模式,其实是一种解决方法,JAVA作为一种面向对象的语言,对于所有的设计模式在实现上,总是少不了对接口的实现,对抽象类的继承,有时候似乎是为了去实现接口而去写接口,所以在这三种模式的说明代码中,我们都定义了接口这些东西,所以才有了现在的混淆。

先不厌其烦的介绍下这三种的设计模式的概念吧。

适配器模式,一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

装饰器模式,原有的不能满足现有的需求,对原有的进行增强。

代理模式,同一个类而去调用另一个类的方法,不对这个方法进行直接操作。

适配器的特点在于兼容,从代码上的特点来说,适配类与原有的类具有相同的接口,并且持有新的目标对象。

就如同一个三孔转2孔的适配器一样,他有三孔的插头,可以插到三孔插座里,又有两孔的插座可以被2孔插头插入。

适配器模式是在于对原有3孔的改造。

在使用适配器模式的时候,我们必须同时持有原对象,适配对象,目标对象。。。。

装饰器模式特点在于增强,他的特点是被装饰类和所有的装饰类必须实现同一个接口,而且必须持有被装饰的对象,可以无限装饰。

代理模式的特点在于隔离,隔离调用类和被调用类的关系,通过一个代理类去调用。

总的来说就是如下三句话:

1 适配器模式是将一个类(a)通过某种方式转换成另一个类(b).

2 装饰模式是在一个原有类(a)的基础之上增加了某些新的功能变成另一个类(b).

3 代理模式是将一个类(a)转换成具体的操作类(b).

又是罗里吧嗦一大段话,然后我们开心的来到了举例时间,这次举的是工作中实际的例子。

先简单介绍一下,公司有一个ORDER系统,专门用于提供订单管理的接口,提供给O2O商城,WAP商城,手机类APP,微信等客户端调用。

ORDER系统在上线之时,已经包含了非常完整的数据操作。

现手机类APP需要升级,老的接口可能不能满足需求,如原O2O订单提货延长有效期接口需要提供截至时间和订单号,新APP可能不提供截至时间,只需要 提供订单号即可延长时间。

而老的接口又不能修改,因为老的order接口是针对所有平台的,那么必须将新接口要求与原接口进行适配。。。

解决方案如下:新增AppAdepter类,用来适配老的接口,同时开发给新的接口。。。。

先给出原接口和实现类

原接口:

/**
 * 原接口,需要传入orderId,时间
 *
 */
public interface SourceOrderApi {
	public void updateDate(String orderId,String date,String client);
}

实现类:

public class SourceOrderApiImpl implements SourceOrderApi{

	@Override
	public void updateDate(String orderId, String date, String client) {
		System.out.println(client+"已将订单"+orderId+"的有效期延长至"+date);
	}
}

在这套代码中,对于客户端来说需要传入orderId  和  有效期date 和客户端名字才能延长。。。

Main方法:

public class Test {

	public static void main(String[] args) {
		SourceOrderApi sourceOrderApi = new SourceOrderApiImpl();
		sourceOrderApi.updateDate("123456", "2014-10-15", "user");
	}

}

运行结果:

而对于新的接口,客户端则不必去传入date 参数

public interface AppOrderApi {
	//只需要传入订单Id即可
	public void updateDate(String orderId,String client);
}

新的实现类:

public class AppOrderApiImpl implements AppOrderApi{

	SourceOrderApi sourceOrderApi;

	public AppOrderApiImpl(){
		sourceOrderApi = new SourceOrderApiImpl();
	}

	@Override
	public void updateDate(String orderId,String client) {
		//这里适配的方式随意,但是保证是要完全兼容原有的,就是保证调用原有的接口
		sourceOrderApi.updateDate(orderId, "9999-12-31",client);
	}

}

main方法:

public class Test {

	public static void main(String[] args) {
		AppOrderApi appOrderApi = new AppOrderApiImpl();
		appOrderApi.updateDate("123456", "user");
	}

}

运行结果:

在这套代码中,新的实现类持有了老接口的对象,就是把这个对象new 出来。。。

然后在新的方法里,进行适配操作。

而这里所谓的适配就是兼容老接口和兼容新接口。

兼容老接口非常简单,就是直接调用老的方法即可。

而兼容新接口就是你所要去做的业务逻辑。。。

比如我这里做了比较简单的操作,app类的统一传入“9999-12-31”,这些都是根据具体的项目需求去实现你的业务代码。

看到这,很多人会觉得 这样的代码是不是很常见。。。。

我自己都特意去翻了一下我之前的代码,很多类似的写法。。。

其实设计模式很多时候都融入到我们的代码中,只是我们没有去理解这种模式,所以就算你自己写出来了,都不知道这是一种适配器模式。。。

设计模式是一种思想,他没有固定的实现代码,我大量查阅了很多大神的的适配器模式解释,大家都不约而同的提到了类的适配和对象的适配,代码中有实现继承这样的写法。当然了,这些大神的写法都是比较标准的。。。

但是仔细再回看下GOF的适配器模式解释。

只需要将原接口转化为客户希望的另一个接口,就是适配器模式!

转化无非就是1.继承原类或者实现原接口  2.持有原接口的对象

再实现目标接口。。。。

那么第一种就是类的适配,第二种就是对象的适配!仅此而已。。。。

那么再回头来说代理模式,在代码上,和适配器模式有着相似的地方!

再比如,现在我们公司的系统又要进行升级,我们原先的接口没有加入安全机制,导致了任何人都可以随意调用这个接口,现在公司需要对这个接口进行改造,只其只能被admin这个客户端调用,其他用户一律要输入账号密码才能调用

那么上面原接口和类不需要改动,我们只需要新增代理器即可。。。

这里就会显出代理模式和适配器模式最大的区别,代理模式是与原对象实现同一个接口,而适配器类则是匹配新接口,说白了,实现一个新的接口。

代理类:

public class ProxySourceOrderApiImpl implements SourceOrderApi {
	SourceOrderApi sourceOrderApiImpl;
	public ProxySourceOrderApiImpl(){
		sourceOrderApiImpl = new SourceOrderApiImpl();
	}

	@Override
	public void updateDate(String orderId, String date, String client) {
		//进行判断,如果是admin则更新否则让其输入账号密码
		if("admin".equals(client)){
			sourceOrderApiImpl.updateDate(orderId, date, client);
		}else{
			System.out.println("账号不是admin,没有查询权限,请输入以admin操作");
		}
	}
}

main方法:

public class Test {

	public static void main(String[] args) {
		SourceOrderApi proxySourceOrderApiImpl = new ProxySourceOrderApiImpl();
		proxySourceOrderApiImpl.updateDate("123456", "2014-10-15", "user");
		proxySourceOrderApiImpl.updateDate("123456", "2014-10-15", "admin");
	}

}

运行结果:

这里的代理类必须要持要实现原接口和持有原接口的对象,才能称之为代理类。

这样,我们不需要修改原先的实现类,用一个代理类来进行过滤。有些人可能有这样的疑惑,为什么不直接在原实现类中修改,记住JAVA设计模式的基本原则,对内关闭修改。

假如你并没有对方的类,别人只是提供给你这样一个可以操作的JAR包你如何去做?把JAR包反编译,再修改?又假如某些地方可以直接调用原有接口,你如果修改原有的实现类,岂不是对其他的地方也造成了影响?不能修改原有代码这是基本原则。

最后,就是装饰器模式,装饰器模式与相对于上面2种模式更好理解,差别也最大。

假如说,现在这个延长订单,不光可以延长订单提货有效期,可以延长订单的退货有效期。

这就是一个典型的装饰器,你需要做的是丰富原接口的功能,并且不改动原先的接口。

public class NewSourceOrderApiImpl implements SourceOrderApi {

	SourceOrderApi sourceOrderApi;
	public NewSourceOrderApiImpl(SourceOrderApi sourceOrderApi){
		this.sourceOrderApi = sourceOrderApi;
	}
	@Override
	public void updateDate(String orderId, String date, String client) {
		sourceOrderApi.updateDate(orderId, date, client);
		System.out.println(client+"已将订单"+orderId+"的退款期延长至"+date);		

	}

}

main方法:

public class Test {

	public static void main(String[] args) {
		SourceOrderApi sourceOrderApi = new NewSourceOrderApiImpl(new SourceOrderApiImpl());
		sourceOrderApi.updateDate("123456", "2014-10-15", "user");
	}

}

运行结果:

在装饰器模式中,必须要有被装饰的类和装饰的类。。在这套代码中,原先SourceOrderApi的对象就是被装饰的类,而新建NewSourceOrderApiImpl 就是装饰类,装饰类必须把被装饰的对象当作参数传入。

这就是和代理模式的代码不同之处,代理模式一定是自身持有这个对象,不需要从外部传入。而装饰模式的一定是从外部传入,并且可以没有顺序,按照代码的实际需求随意挑换顺序,就如你吃火锅先放白菜还是先放丸子都可以。

再从使用上来看,代理模式注重的是隔离限制,让外部不能访问你实际的调用对象,比如权限控制,装饰模式注重的是功能的拓展,在同一个方法下实现更多的功能。

啰啰嗦嗦一大篇文章,大概是把这三种模式好好的整理一下,个人本身也是彻底理解了这三种模式。

现在可以安心的进入下一个环节学习了。。。

匆匆拙笔,如有疏漏错误,敬请指出

时间: 2024-10-12 09:16:58

菜鸟版JAVA设计模式—适配器模式,装饰模式,代理模式异同的相关文章

一起学java设计模式--适配器模式(结构型模式)

适配器模式 现有一个接口DataOperation定义了排序方法sort(int[]) 和查找方法search(int[], int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法,类BinarySearch 的binarySearch(int[], int)方法实现了二分查找算法.现使用适配器模式设计一个系统,在不修改源代码的情况下将类QuickSort和类BinarySearch的方法适配到DataOperation接口中.绘制类图并编程实现. (要求实现

菜鸟版JAVA设计模式—从买房子看代理模式

今天学习了代理模式. 相对于适配器模式,或者说装饰器模式,代理模式理解起来更加简单. 代理这个词应该比较好理解,代替去做就是代理. 比如,我们买卖房子,那么我们会找中介,我要卖房子,但是我们没有时间去卖,我主动交给中介,中介会帮我发布,会帮我找买家,带买家看房,最后我只要收到钱就行了. 买家的目的:卖房拿钱..卖加最终的目的就是把房子换成钱. 中介的工作:收集房产信息,发布房产信息,等买家打电话来,带买家看房,买家看中了,付钱给中介,中介办理过户手续,过户成功,抽掉自己的佣金,付钱给卖家. 卖家

菜鸟版JAVA设计模式—从火锅底料到装饰器模式

今天开始学历了JAVA设计模式中的装饰模式,照例还是写下自己理解的心得吧. 装饰器模式,啥是装饰器模式?带着这个问题,咱们好好的去火锅店吃个火锅. "老板,来份全辣锅底,不要给我用装饰器模式来配料!"我特地狠狠的强调了最后一句话. 不到一会,老板给我端来了一个火锅和几个盘子,火锅里装了盐水,而盘子里放了辣椒,花椒,茴香,大蒜等佐料.......... 这时候大家可能就需要问了,这咋吃啊...难道让我自己配料么? 这便是是我们的矛盾了!客户需要的一盘已经配好料的火锅汤底,但是我们初期给用

Java设计模式—Proxy动态代理模式

代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代理模式 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性.Java 动态代理机制以巧妙的方式近乎完

Java设计模式9:代理模式

代理模式 代理模式的定义很简单:给某一对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结构 有些情况下,一个客户不想活着不能够直接引用一个对象,可以通过代理对象在客户端和目标对象之间起到中介作用.代理模式中的角色有: 1.抽象对象角色 声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象 2.目标对象角色 定义了代理对象所代表的目标对象 3.代理对象角色 代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象:代理对象提供一个与目标

Java 设计模式(八) Proxy(代理)模式及Spring引申

Proxy 基本概念 代理模式(Proxy pattern)是一种使用率非常高的模式: 为其他对象提供一种代理以控制对这个对象的访问 代理模式也叫作委托模式,它是一项基本设计技巧 Proxy中的角色 Subject(抽象主题类):既可以是抽象类也可以是抽象的接口 RealSubject(具体的主题角色):是被委托角色或者说是被代理角色 Proxy(代理主题角色):是委托类或者代理类: 它负责对真实的角色的应用 把Subject定义的方法限制委托给RealSubject实现 在RealSubjec

《Java设计模式》之代理模式

1,什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 2,策略模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 3,代理模式一般涉及到的角色有: 抽象角色:声明真实对象和代理对象的共同接口: 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象.同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当

Java设计模式之《代理模式》及应用场景

代理模式算是我接触较早的模式,代理就是中介,中间人.法律上也有代理,比如代理律师之类,委托人将自己的一部分权限委托给代理者,代理者就拥有被代理者(委托人)的部分权限,并且可以以被代理人的名义来实行这些权限,此时代理者与委托人等同,当然代理人也可以在实行权限时配合自己的能力来进行,当然不能超出这个权限. Java中的代理模式类似于上面的代理,我们也是为一个类(委托类)创建一个代理类,来代表它来对外提供功能. 如何在Java中创建一个类的代理类呢? 很简单,我们需要创建一个公共接口,委托类要实现这个

java设计模式详解:代理模式

代理模式就是用一个第三者的身份去完成工作,其实际意义跟字面意思其实是一样的,理解方式有很多,还是例子直观. 本例的实现类是实现买票功能,实际应用想要添加身份验证功能,利用代理模式添加验证步骤.上例子: package com.learn.proxy.proxyModel; /** * 初始功能接口,买票 * @author garfield * */ public interface Tickets { public abstract void buy(); } package com.lear