- 浏览: 830821 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (379)
- struts (5)
- hibernate (16)
- spring (16)
- ssh (20)
- MySQL (16)
- 数据库脚本 (2)
- DownLoad (1)
- GAE (5)
- Java (103)
- LoadRunner (2)
- VF (1)
- 学习资料 (24)
- 软件使用 (21)
- 通信类 (4)
- 生活 (3)
- J2ME (1)
- 心理学 (1)
- Linux (26)
- Android (3)
- Oracle (1)
- 面向对象概念&面试准备 (11)
- ExtJs (2)
- Google Map (1)
- Flex (47)
- 算法研究 (1)
- share (20)
- python (1)
- MongoDB (7)
- centos6 (13)
- C++ (8)
- DB2 (3)
- C# (1)
- 代码片段 (24)
- Lucene (2)
- php (1)
- NodeJS (1)
- Express (1)
最新评论
-
shua1991:
已阅,我表示同意。
Eclipse统计代码行数 -
nakedou:
写的不错,挺详细的
在CentOS中使用 yum 安装MongoDB及服务器端配置 -
sjp524617477:
好方法
Eclipse统计代码行数 -
simpletrc:
<script>ale ...
Java写到.txt文件,如何实现换行 -
csdn_zuoqiang:
Apache Ftp Server,目前是1.0.4,非常好的 ...
Apache FtpServer在64位系统下服务不能启动解决方法
假设模型:媒体播放器,既能播放音频文件AudioMedia,又能播放视频文件VideoMedia 。其中音频文件又分MP3格式和WMV格式;视频文件又分MPEG格式和RM格式。
经过功能分析,不管哪种类型的文件都要有一个播放的方法,也就是Play() ,原型结构如图:
当各个类之间继承/实现关系理清楚后,我们现在可以实现一个播放器类MediaPlayer,它可以播放任何一种格式(MP3、WAV、RM、MPEG)的文件。 在此我们要注意一点:在调用类对象的属性和方法时,尽量避免将具体类对象作为传递参数,而应传递其抽象对象,更好地是传递接口,将实际的调用和具体对象完全剥离开,这样可以提高代码的灵活性。(使用接口有什么好处?那就是你的主程序可以在没有具体业务类的时候,同样可以编译通过。因此,即使你增加了新的业务,你的主程序是不用改动的。) 在本文中体现在MediaPlayer代码中,如下所示: package adapter_media; public class MediaPlayer { public void Play(IMedia media){ media.Play(); } }
相关代码如下:
package adapter_media;
public interface IMedia {
public void Play();
}
package adapter_media;
public abstract class AudioMedia implements IMedia{
public abstract void Play();
}
package adapter_media; public abstract class VideoMedia implements IMedia { public abstract void Play(); }
package adapter_media; public class MP3 extends AudioMedia { @Override public void Play() { System.out.println("Play AudioMedia with the type of MP3"); } }
package adapter_media; public class WAV extends AudioMedia { @Override public void Play() { System.out.println("Play AudioMedia with the type of WAV"); } }
package adapter_media; public class MPEG extends VideoMedia { @Override public void Play() { System.out.println("Play VideoMedia with the type of MPEG"); } }
package adapter_media; public class RM extends VideoMedia { @Override public void Play() { System.out.println("Play VideoMedia with the type of RM"); } }
package adapter_media; /** ************************************* * @Title MediaPlayer.java * @Author 张作强 * @Date 2010-8-15 * @Comment 在调用类对象的属性和方法时,尽量避免将具体类对象作为传递参数, * 而应传递其抽象对象,更好地是传递接口, * 将实际的调用和具体对象完全剥离开,这样可以提高代码的灵活性。 ************************************* */ public class MediaPlayer { public void Play(IMedia media){ media.Play(); } }
引入Adapter模式:
原来的RM和MPEG类继承了VideoMedia抽象类,而VideoMedia类又实现了IMedia接口,该接口仅仅提供了Play()方法。现在我们希望为RM,MPEG提供与AudioMedia不同的属性和方法。例如,对于视频媒体而言,应该有一个调整画面大小的方法,如Resize()。而这个方法是IMedia接口所不具备的。
那么怎样为RM,MPEG类提供IMedia接口所不具备的Resize()方法呢?非常自然地,通过这个问题我们就引出Adapter模式的命题了。首先,要假设一个情况,就是原文的所有代码,我们是无法改变的,这包括暴露的接口,类与接口的关系等等,都无法通过编码的方式实现新的目标。只有这样,引入Adapter模式才有意义。
Adapter模式分为两种:类的Adapter模式、对象的Adapter模式。
下面试图根据本例对两种方式进行说明及实现。在实现Adapter模式之前,有必要看看原来的类结构:
一、类的Adapter模式
既然要让RM、MPEG具有Resize()方法,最好的办法就是让它们直接实现IVideoScreen接口。然而受到条件的限制,这两个类的类型是不可修改的。唯一可行的办法就是为相应的类新引入一个类类型,这就是Adapter模式中所谓的Adapter类了。它好比是一个转接头,通过它去实现IVideoScreen接口,同时又令其继承原有的RM或MPEG类,以保留原有的行为。类图如下:
图中的类RMAdapter和MPEGAdapter就是通过Adapter模式获得的对象,它在保留了原有行为的同时,又拥有了IVideoScreen的功能。
相关代码如下:
也许很多人已经注意到了,在使用这种方式建立Adapter时,存在一个局限,就是我们必须为每一个要包裹(Wrapping)的类,建立一个相应的Adapter类。如上所述的RM对应RMAdapter,MPEG对应MPEGAdapter。必须如此,为什么呢?虽然RM和MPEG继承了同一个抽象类VideoMedia,但其Play()方法,可能是不相同的。此时,相对应的Adpater类只有直接继承该具体类,方才可以保留其原来的Play()方法的行为本质。 package adapter_media;
public interface IVideoScreen {
public void Resize();
}
package adapter_media;
public class MPEGAdapter extends MPEG implements IVideoScreen {
public void Resize() {
System.out.println("Play VideoMedia with the size of MPEG");
}
@Override
public void Play() {
super.Play();
}
}
package adapter_media;
public class RMAdapter extends RM implements IVideoScreen {
public void Resize() {
System.out.println("Play VideoMedia with the size of RM");
}
@Override
public void Play() {
super.Play();
}
}
评论
二、对象的Adapter模式
对象的Adapter模式,与类的Adapter模式,最大的区别就是不采用继承的方式,而是将要包裹的对象,以聚合的方式放到Adapter中,然后用委托的方式调用其对象的方法,实现类图如下:
以这种方式形成的VideoAdapter,由于没有和RM、MPEG直接发生关系,并通过在构造函数传递参数的方式,等待客户端使用Adapter时,才将具体的VideoMedia对象传递给Adapter,显得耦合度更加松散,更加灵活。
对于对象的Adapter模式(在VideoMedia)中,按照传递对象的方式又可以分为:通过构造函数传递被包裹对象的方式、通过方法属性方式传递被包裹对象。
相关代码如下:
package adapter_media; public class VideoAdapter implements IVideoScreen { private VideoMedia _video; //无参构造函数 public VideoAdapter() { } //构造函数方式传递对象 public VideoAdapter(VideoMedia videoMedia) { this._video = videoMedia; } //方法属性方式传递对象,同时要求此类必须有一个无参构造函数 public void setVideoMedia(VideoMedia video) { this._video = video; } public void Play() { _video.Play(); } public void Resize() { System.out.println("Play VideoMedia with the size of " + _video.getClass().getSimpleName()); } }
测试类:
package adapter_media; /** ************************************* * @Title TestMedia.java * @Author 张作强 * @Date 2010-8-15 * @Comment 原有类型和经过Adapter扩展后的类型 ************************************* */ public class TestMedia { public static void main(String[] args) { IMedia mp3 = new MP3(); IMedia wav = new WAV(); IMedia rm = new RM(); IMedia mpeg = new MPEG(); MediaPlayer media = new MediaPlayer(); System.out.println("================ type ================="); media.Play(mp3); media.Play(wav); media.Play(rm); media.Play(mpeg); System.out.println("============= 类的Adapter模式 ============="); IVideoScreen rmAdapter = new RMAdapter(); rmAdapter.Resize(); ((RMAdapter) rmAdapter).Play(); IVideoScreen mpegAdapter = new MPEGAdapter(); mpegAdapter.Resize(); ((MPEGAdapter) mpegAdapter).Play(); System.out.println("=============== 对象的Adapter模式(构造函数方式传递对象) ==============="); VideoAdapter rmAdapter2 = new VideoAdapter(new RM()); rmAdapter2.Play(); rmAdapter2.Resize(); VideoAdapter mpegAdapter2 = new VideoAdapter(new MPEG()); mpegAdapter2.Play(); mpegAdapter2.Resize(); System.out.println("=============== 对象的Adapter模式(方法属性方式传递对象) ==============="); VideoAdapter rmAdapter3 = new VideoAdapter(); rmAdapter3.setVideoMedia(new RM()); rmAdapter3.Play(); rmAdapter3.Resize(); VideoAdapter mpegAdapter3 = new VideoAdapter(); mpegAdapter3.setVideoMedia(new MPEG()); mpegAdapter3.Play(); mpegAdapter3.Resize(); } }
结果:
================ type ================= Play AudioMedia with the type of MP3 Play AudioMedia with the type of WAV Play VideoMedia with the type of RM Play VideoMedia with the type of MPEG ============= 类的Adapter模式 ============= Play VideoMedia with the size of RM Play VideoMedia with the type of RM Play VideoMedia with the size of MPEG Play VideoMedia with the type of MPEG =============== 对象的Adapter模式(构造函数方式传递对象) =============== Play VideoMedia with the type of RM Play VideoMedia with the size of RM Play VideoMedia with the type of MPEG Play VideoMedia with the size of MPEG =============== 对象的Adapter模式(方法属性方式传递对象) =============== Play VideoMedia with the type of RM Play VideoMedia with the size of RM Play VideoMedia with the type of MPEG Play VideoMedia with the size of MPEG
比较两种实现方式的类图,可以得出两个结论:
1、 对象的Adapter模式,减少了对象的个数;
2、 耦合度更加松散;
通过运用Adapter模式,扩展了新的接口,而原有的类型并不需要做任何改变,这就是Adapter模式的实质,也是为什么取名为Adapter的原因之所在了。同时,我们要注意的是,在运用Adapter模式时,必须审时度势,根据具体的情况,抉择最优的方式,或者采用类的Adapter模式,或者采用对象的Adapter模式。决定权在与你,菜单给你送上来了,看看自己的腰包,想想点什么样的菜吧。
参考地址:http://www.cnblogs.com/wayfarer/articles/70453.html
发表评论
-
微信JS
2013-10-26 21:17 2039<div class="iteye-blog- ... -
ubuntu下MySQL用source命令导入sql文件出现乱码解决方法
2012-11-18 23:46 1483首先建立数据库的时候指明数据库编码如: CREA ... -
RandomAccessFile
2012-10-18 18:16 941public void run() { try { ... -
java中多种方式读文件
2012-10-18 16:53 925java中多种方式读文件一、多种方式读文件内容。1、按字节读取 ... -
FileChannelMain
2012-10-15 18:12 1072package scan; import java ... -
Apache FtpServer在64位系统下服务不能启动解决方法
2012-06-10 21:29 6799Apache FTPServer是一款用Java开发的 ... -
Java 集合类
2012-06-07 22:03 1564Java 集合类 1. 为什么要了解J ... -
short、int、long与byte之间的转换工具类
2012-05-31 11:05 4476/** * 各基础类型与byte之间的转换 * ... -
Linux Mint 13 配置JAVA 环境
2012-05-24 22:35 26190.1--下载 JAVA ... -
FatJar+Exe4j+Inno Setup 生成可执行的exe文件
2012-04-17 10:54 14241、fatjar 是Eclipse的一个免费的插件。它的 ... -
JPanel JTextField add Focus 获取焦点解决方案
2012-03-30 21:29 2979public class TabPagePanel ex ... -
JList List<E> Page 分页
2012-03-30 21:28 1730package view.retrieve.comps. ... -
JButton setAction的BUG
2012-03-23 10:53 1276今天在使用JButton的时候,想用setText()setI ... -
自定义JTabbedPane皮肤
2012-03-22 12:05 4709package ui; import java.awt. ... -
两个工具类
2012-03-17 21:27 863package com.retrieve.utils; ... -
两个工具类
2012-03-17 21:27 0package com.retrieve.utils; ... -
mysql、sqlserver、oracle分页,java分页统一接口实现
2012-03-13 17:56 0定义: pageStart 起始页,pageEnd 终止页, ... -
Invalid command: InetLoad::load
2012-03-06 16:41 1284Invalid command: InetLoad::load ... -
NIO: High Performance File Copying
2012-03-01 17:25 1148In a previous tip, I discussed ... -
自定义JList
2012-02-03 15:39 773自定义JList。
相关推荐
一些书籍也称适配器模式为缺省适配器模式(Default Adapter Pattern) 。 适配器模式主要分 为三类: 类适配器模式、 对象适配器模式、 接口适配器模式。 以生活中手机充电为例来讲解适配器模式, 手机本身并不能...
c++设计模式-结构型模式-适配器模式,其他工程,c++源码。适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
适配器模式 设计模式 Adapter 还请各位大S指教
走进设计模式之——适配器模式 (Adapter) 对应代码
java 汽车适配器(Adapter适配器模式) java 汽车适配器(Adapter适配器模式)
适配器模式是一种结构型设计模式,它允许接口不兼容的两个类可以协同工作。以下是该模式的要点: 1. **角色**: - **Target(目标接口)**:客户端期望调用的接口。 - **Adaptee(适配者)**:现有的、接口与目标...
设计模式C++学习之适配器模式(Adapter)
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要... 这是第7节:结构型模式Adapter 适配器模式
Adapter(适配器)模式[定义].pdf
- 适配器模式(Adapter) - 装饰器模式(Decorator) - 桥接模式(Bridge) - 组合模式(Composite) - 外观模式(Facade) - 享元模式(Flyweight) - 观察者模式(Observer) - 模板方法模式(Template Method) - 策略...
C#设计模式之适配器模式应用实例
1. 概述 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。 2. 解决的问题 ... 注:在GoF的设计模式中,对适配器模式讲了两种类型
C#面向对象设计模式纵横谈(7):Adapter 适配器模式(结构型模式) 体验课程
java设计模式之适配器模式,希望对大家有所帮助。
基于类的Adapter模式的一般结构如下:Adaptee类为Adapter的父类,Adaptee类为适配源,适配目标(接口)也是Adapter的父类;基于类的Adapter模式比较适合应用于Adapter想修改Adaptee的部分方法的情况。 基于对象的...
javascript设计模式之Adapter模式【适配器模式】实现方法示例.docx
C#面向对象设计模式 Adapter 适配器模式 视频讲座下载
C#面向对象设计模式纵横谈(7):Adapter 适配器模式(结构型模式) (Level 300)
Adapter适配器模式在JavaScript设计模式编程中的运用分析_.docx