论坛首页 Java企业应用论坛

了解适配器模式

浏览 10615 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-12-01   最后修改:2008-12-05

     客户端通过类的接口访问提供的服务,一般现有类可提供用户的所需功能,而有时不能满足用户的期望。例如有两个毫无关联的类组合在一起使用,要么就是修改各自的接口,但是在不修改各自接口的前提下,应该怎么做呢?使用Adapter模式,使得原本需要修改接口的才能在一起工作的两个类可以通过此模式不进行修改接口,在一起工作。

     举个例子,面包制作商可以制作面包,蛋糕制作商可以制作蛋糕,某工厂以前请了面包制作商只做面包,而现在还要制作蛋糕。

     传统方法 增加一个蛋糕制作的接口,并且在实现中增加制作蛋糕的实现。

public interface MakeFactory{
	String getCake();
	String getBread();
}

 实现:

public class MakeFactoryImpl implements MakeFactory{

	public String getBread() {
		// TODO Auto-generated method stub
		return null;
	}

	public String getCake() {
		// TODO Auto-generated method stub
		return null;
	}

}

 这样就ok了。

但是想想,以前他是做面包的,有做面包的一套体制,如果再把做蛋糕加进去,工序有可能会乱。并且无法工作。

这样我们可以通过Adapter模式。

   

/**
 * Adaptee 被适配器
 * */
public class MakeBread {
	public String getBread(){
		System.out.println("++++++bread++++");
		return "bread";
	};
}

 以前我只有一个面包房,现在我还要蛋糕房

public interface MakeFactory{
	String getCake();
	String getBread();
}

  

 最后看看如何通过适配器模式,将不相连的两个类配在一起工作。

/**
 * Adapter 适配器
 * */
public class MakeCake extends MakeBread implements MakeFactory {
	public String getCake() {
		System.out.println("++++++cake++++");
		return "cake";
	};
}

 

这样做,我们的MakeFactory工厂就可以有条不紊的进行制作。

我们测试一下

public class Client {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MakeCake m = new MakeCake();
		m.getCake();
		m.getBread();
	}
}

 

测试结果

++++++cake++++
++++++bread++++

 

从这里不难看出,此接口可以满足用户的需要。

   发表时间:2008-12-01  
Atapter


错了吧

Adapter
0 请登录后投票
   发表时间:2008-12-01  
zhajie 写道

Atapter 错了吧 Adapter

谢谢了,
初学者,请见谅,哈哈
0 请登录后投票
   发表时间:2008-12-02  
- -! 娃 跟设计模式4磕了?
0 请登录后投票
   发表时间:2008-12-02  
当初第一次看到时真的感觉蛮震撼的。。。。
0 请登录后投票
   发表时间:2008-12-02  
tou3921 写道

当初第一次看到时真的感觉蛮震撼的。。。。

人嘛,都是在不断学习中进步的,错了能改就好了,也同样感谢帮助和指导
0 请登录后投票
   发表时间:2008-12-08  
运行机制有点看不明白, 还望解释下
0 请登录后投票
   发表时间:2008-12-08   最后修改:2008-12-08
说明:在本回复中所有出现的语句都没调试过,如果有语法错误,望理解。

在我的认知世界中,适配器模式是最强悍的模式。

适配器模式,通俗说,大轮子套小轮子。

说白了:把一个类的实例,注入到另一个类中,而这个类的方法就调用前一个类的方法。
例: (非java语言,为了描述形象采用,类似java语法,希望 大家能看懂)

如果有这个类
 public Class ClassA.{ //这就是通俗说法中的小轮子
    public void methodA(){//其他语句 } 
}


则适配器模式中 ,ClassB 则如下定义了

public Class ClassB{ //这就是通俗说法中的大轮子
      public  ClassA aObj; //aObj是一个ClassA变量
      public void methodB() { 
          //其他语句
          aObj.mehtoidA;
          //其他语句
       } 
}



在使用ClassB 时,要先给aObj注入一个ClassA实例。
如下:
  ClassA a=new ClassA(); 
   ClassB b =new ClassB();
   b.aObj=a;
   b. methodB();

当然了,向ClassB 注入ClassA的实例时,方法多种多样。既可通过ClassB的构造方法,也可在ClassB用getter and setter方法注入,还可在methodB方法中通过参数注入  等等。


好处之一是: 当ClassA是第三方提供的类,我们根本就不可能修改其源代码,而此时我们既想想使用它提供的方法,又想适当改变,则适配器模式就用上了。

适配器模式,博大精深,我不想发表我自已的感悟了,免得又遇到很浑的牛人。 

再次强调,适配器模式的内涵,博大精深。就像道家的阴阳、哲学中的矛盾, 看似平凡无奇,实质上23中模式及其他模式,多半都能分解到适配器模式中来。不说了,不说了,设计模式与数据结构,重点在领悟其内涵。


0 请登录后投票
   发表时间:2008-12-08  
wangchao_17915566 写道
tou3921 写道

当初第一次看到时真的感觉蛮震撼的。。。。

人嘛,都是在不断学习中进步的,错了能改就好了,也同样感谢帮助和指导



javaeye中所有人像你这种想法就对了。
0 请登录后投票
   发表时间:2008-12-08   最后修改:2008-12-08
下面摘自李建忠(当年MSDN,CSDN请的讲师)的讲义
===========================

引:在现实环境中,经常需要“引用现在的一些对象”到新的环境中去,但是新的环境中的要求的接口是“这些存在对象”不满足的。
意图:将一个类的接口转换成用户所需要的接口。适配器模式使哪些原本因接口而不能一起工作的类可以一起工作。
===========================

对了,这是讲c#的。有的网友别迂腐到讲c#的设计模式,就不能用到java中了。要是这样,我只能无语。


在上面的UML类图中,Target表成了一个类。实际中,这个要么是一个接口(java中的interface,与李建忠讲义的意图中的接口的概念有点不一样。)。Adaptee就是第三方提供的类。而客户中的代码,不希望直接使用这个第三方类的,于是通过Adapte使用。抛掉Target,就是前面我说的大轮子套小轮子。


适配器从实现的角度上看,是把一个类实例(假如叫objA),注入到另一个类(假定这个类叫类B)中,在这个类B中的方法,使用前面所说的类的实例(即objA)的方法。

从适配器意图上看:它是解决两套接口标准不同的问题。举个例子:
假定有个第三方类叫Man(即人),定义并实现了一个方法叫 feed (吃饭),而这个方法中没有任何参数了。客户不能改变第三方的类的源代码,但是由于实际需要,它想要在这Man的feed方法中加入一个参数---吃饭时间。这时如何办呢?
就是另定义一个类FMan,也定义一个方法,这个方法有一个参数---吃饭时间,在这个类(即FMan)中需要传入Man的实例,在FMan的feed方法里,调用Man实例的feed方法。


在这个适配器中,适配器的实现角度,可以进行总结,推广,再进行新的定义,就会发现这个适配器的内涵,博大精深。如果喜欢佛家之悟的朋友,可把接口、抽象类、适配器模式,联合起来进行观察体会,找出他们的相同点、不同点,会发现这个适配器,真的像机器中的螺丝,它把各个部件有机的组合在一起了。这是一个高度抽象的东东,如果要讲清,需要定义一大套的词语的含义。关于这个适配器模式,就到此为止吧。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics