模式设计(七)Adapter

本文介绍了适配器模式的概念及其实现方式,包括类适配器模式和对象适配器模式的区别。通过C#和Pascal示例展示了如何将不同接口的对象适配到统一接口,以实现代码复用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       之前我们已经介绍完了创建型模式,它们分别为Factory Method,Abstract Factory,Singleton,Builder,Prototype。创建型模式是创建对象而不是直接实例化对象,这会使程序在判断给定情况下创建哪个对象时更为灵活。在C#中为new,在Pascal中为Create。
       接下来我们要介绍结构型模式,这类模式可以将一组对象组合成更大的结构。对于结构型模式(Structural Pattern)来说主要分为两种组合方式,分别为类模式和对象模式,其主要区别为类模式描述的是如何使用继承提供更有用的程序接口,而对象模式描述的是通过使用对象组合或将对象包含在其他对象里,将对象组合成更大的结构。
       下面我们来看看结构型的第一种模式适配器模式(Adapter Pattern)。
       适配器模式可以将类的接口转变成客户需要的其他接口。这样做的好处就是能很好的复用已有的代码,比如很多公司都生产数据库,如Oracle,IBM,Microsoft,它们的产品各有各的特点,原生的开发方法也有很大的区别,比如Oracle提供OCI接口,Sql Server提供自己专用的API。如果都使用数据库厂商的原生开发方法,那么在Sql Server开发的软件就很难移植到其他的数据库平台上去,这无疑会限制产品的应用范围。为此很多厂商就提供了各种标准的开发接口,比如最早的ODBC,BDE,到现在的ADO.NET等等,有了这种标准的数据库开发接口,我们在一个平台上开发的产品就很容易移植到其他平台上去。
    那么如何让数据库适应不同的标准API而无需大的改动呢,这就是通过适配器模式来实现了,微软最早的ODBC Driver和现在的ADO.NET就相当于一个适配器,可以让数据库适应不同的标准开发接口。这样原有的产品无需针对标准的API做任何改变,只要针对不同的开发API实现一个Dirver就可以了。
       适配器模式的实现原理很简单,就是通过实现了客户指定接口的类来响应客户的请求,然后在适配器内部将请求转发给原有的API接口对应的具有类似功能的方法,然后将处理的结果整理后返回给客户。
        适配器模式有类的适配器模式和对象的适配器模式两种。我们将分别讨论这两种Adapter模式。

     类的Adapter模式的结构:

由图中可以看出,AdapteeXML类没有CreateFile方法,而客户期待这个方法。为了使客户能够使用AdapteeXML类,提供一个中间环节,即类Adapter类,Adapter类实现了ISerTarget接口,此接口中定义了CreateFile方法,并继承自AdapteeXML,Adapter类的CreateFile方法重新封装了AdapteeXMl的CreateXMLFile方法,实现了适配的目的。<?xml:namespace prefix = o />

因为Adapter与AdapteeXML是继承的关系,所以这决定了这个适配器模式是类的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。因为C#不支持多继承,所以Target必须是接口,不可以是类,这里为ISerTarget。
源(Adaptee)角色:需要适配的类,这里为AdapteeXML。
适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类。
以上例子主要是一个XML串行化实例(C#):

 1None.gifusing System;
 2None.gifusing System.IO;
 3None.gifusing System.Xml.Serialization;
 4None.gifusing System.Xml;
 5None.gifnamespace AdapterClass
 6ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 7ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 8InBlock.gif    ///============== Program Description==============
 9InBlock.gif    ///Name:AdapterClass.cs
10InBlock.gif    ///Objective:AdapterClass 
11InBlock.gif    ///Date:2006-05-04 
12InBlock.gif    ///Written By coffee.liu
13InBlock.gif    ///================================================
14ExpandedSubBlockEnd.gif    /// </summary>

15InBlock.gif    class Class1
16ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
17ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
18InBlock.gif        /// 应用程序的主入口点。
19ExpandedSubBlockEnd.gif        /// </summary>

20InBlock.gif        [STAThread]
21InBlock.gif        static void Main(string[] args)
22ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
23InBlock.gif            ISerTarget target=new Adapter();
24InBlock.gif            target.CreateFile();
25InBlock.gif            Console.WriteLine("xml file created");
26ExpandedSubBlockEnd.gif        }

27ExpandedSubBlockEnd.gif    }

28InBlock.gif    [Serializable]
29InBlock.gif    public class Person
30ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
31InBlock.gif        public string Name;
32InBlock.gif        public string Sex;
33InBlock.gif        public DateTime Brith;
34InBlock.gif        private int PersonID;
35InBlock.gif        public Person()
36ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{}
37InBlock.gif        public void SetID(int ID)
38ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{PersonID=ID;}
39ExpandedSubBlockEnd.gif    }

40InBlock.gif
41InBlock.gif    interface ISerTarget
42ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
43InBlock.gif        void CreateFile();
44ExpandedSubBlockEnd.gif    }

45InBlock.gif    class Adapter:AdapteeXML,ISerTarget
46ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
47InBlock.gif        public Adapter():base()
48ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
49ExpandedSubBlockEnd.gif        }

50InBlock.gif
51InBlock.gif        public  void CreateFile()
52ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
53InBlock.gif            this.FillData();
54InBlock.gif            this.CreateXMLFile();
55InBlock.gif      
56ExpandedSubBlockEnd.gif        }

57InBlock.gif    
58ExpandedSubBlockEnd.gif    }

59InBlock.gif    class AdapteeXML
60ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
61InBlock.gif        FileStream aFile;
62InBlock.gif        Person aPerson;
63InBlock.gif        XmlSerializer aXML;
64InBlock.gif        public AdapteeXML()
65ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
66InBlock.gif            aXML=new XmlSerializer(typeof(Person));
67InBlock.gif            aPerson=new Person();
68ExpandedSubBlockEnd.gif        }

69InBlock.gif        public void FillData()
70ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
71InBlock.gif            aPerson.Name="XML";
72InBlock.gif            aPerson.Sex="";
73InBlock.gif            aPerson.Brith=DateTime.Now;
74InBlock.gif            aPerson.SetID(1);
75ExpandedSubBlockEnd.gif        }

76InBlock.gif        public void CreateXMLFile()
77ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
78InBlock.gif            try
79ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
80InBlock.gif                aFile=new FileStream("Person.xml",FileMode.Create);
81ExpandedSubBlockEnd.gif            }

82InBlock.gif            catch(IOException e)
83ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
84InBlock.gif                Console.WriteLine("some error happened!");
85InBlock.gif                Console.WriteLine(e.ToString());
86InBlock.gif                return;
87ExpandedSubBlockEnd.gif            }

88InBlock.gif            aXML.Serialize(aFile,aPerson);
89InBlock.gif            aFile.Close();
90ExpandedSubBlockEnd.gif        }

91ExpandedSubBlockEnd.gif    }

92ExpandedBlockEnd.gif}

93None.gif
当然用Pascal也可以实现同样的功能,我们看看如何将上面的XML文件读取出来,这里只给出功能性代码,具体扩展希望读者自己思考。
代码(Pascal):
 1None.gifprogram AdapterClass;
 2None.gif  //============== Program Description==============
 3None.gif    //Name:AdapterClass.dpr
 4None.gif    //Objective:AdapterClass
 5None.gif    //Date:2006-05-04
 6None.gif    //Written By coffee.liu
 7None.gif    //================================================
 8None.gif{$APPTYPE CONSOLE}
 9None.gif
10None.gifuses
11None.gif  SysUtils,msxmldom,XMLDoc, oxmldom, xmldom, XMLIntf,windows;
12None.gif  type ISerTarget=interface
13None.gif    function ReadFile():string;
14None.gif    end;
15None.gif  type AdapteeXML=class
16None.gif      xmlDocument1 :IXMLDocument;
17None.gif      node:IXMLNode;
18None.gif      count:Integer;
19None.gif      constructor Create;
20None.gif      function ReadFromXml(Node:IXMLNode;Count:integer):string;
21None.gif    end;
22None.gif  type Adapter= class(AdapteeXML,ISerTarget)
23None.gif    private
24None.gif     FRefCount : Integer;
25None.gif     public 
26None.gif    function QueryInterface(const IID:TGUID;out Obj):HRESULT;stdcall;
27None.gif    function _AddRef:Integer;stdcall;
28None.gif    function _Release:Integer;stdcall;//这里让接口引用计数器来控制对象生存周期了,这里我为了少写代码没有人为的去控制对象的生存周期,当然读者也可以通过继承TInterfacedObject对象来完成IInterface。    function ReadFile():string;
29None.gif    constructor Create;
30None.gif   end;
31None.gif
32None.gif
33None.gif{ AdapteeXML }
34None.gif
35None.gifconstructor AdapteeXML.Create;
36None.gifbegin
37None.gif    xmlDocument1 :=TXMLDocument.Create(nil);
38None.gif    xmlDocument1.LoadFromFile('D:\coffee.liu\Delphi7\Projects\Person.xml');//上面C#例子创建出的XML文件
39None.gif    XMLDocument1.Active:=true;
40None.gif    count:=xmlDocument1.ChildNodes.Count;
41None.gif    node:= xmlDocument1.DocumentElement;
42None.gifend;
43None.gif
44None.giffunction AdapteeXML.ReadFromXml(Node:IXMLNode;Count:integer):string;
45None.gifvar
46None.gifi:integer;
47None.gifbegin
48None.gif            for i := 1 to Count-1 do begin
49None.gif                if(node<>nil) then
50None.gif                 result:=Node.ChildNodes['Name'].Text+';'+Node.ChildNodes['Sex'].Text+';'+Node.ChildNodes['Brith'].Text
51None.gif
52None.gif            end;
53None.gif            xmlDocument1.Active:=false;
54None.gifend;
55None.gif{ Adapter }
56None.gif
57None.giffunction Adapter._AddRef: Integer;
58None.gifbegin
59None.gif   Result := InterlockedIncrement(FRefCount);
60None.gifend;
61None.gif
62None.giffunction Adapter._Release: Integer;
63None.gifbegin
64None.gif   Result := InterlockedDecrement(FRefCount);
65None.gif    if Result = 0 then
66None.gif   Destroy;
67None.gifend;
68None.gif
69None.giffunction Adapter.QueryInterface(const IID: TGUID; out Obj): HRESULT;
70None.gifbegin
71None.gif   if GetInterface(IID, Obj) then
72None.gif    Result := 0
73None.gif  else
74None.gif    Result := E_NOINTERFACE;
75None.gifend;
76None.giffunction Adapter.ReadFile():string;
77None.gifbegin
78None.gif   self.ReadFromXml(self.node,self.count);
79None.gifend;
80None.gifconstructor Adapter.Create;
81None.gifbegin
82None.gifinherited;
83None.gifend;
84None.gifvar
85None.gifaAdapter:Adapter;
86None.gifbegin
87None.gif  aAdapter:=Adapter.Create;
88None.gif  Writeln(aAdapter.ReadFile);
89None.gifend.
90None.gif
     
        对象的Adapter模式的结构:
11.gif
WebResource.axd?d=pLXXeGbWF7eXU8SMs2-GFZvUWY2JNH05dFx5YzJhGUYAYJAFEaTEq36NAhTPy7_KekvzDFwt8wvQWdByvJIGWdEq6x2KpKD80&t=632785713320000000
 

从图中可以看出:客户端需要调用CreateFile方法,而AdapteeXML,AdapteeSoap,AdapteeBin没有该方法,为了使客户端能够使用AdapteeXXX类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装AdapteeXXX的实例,从而将客户端与AdapteeXXX衔接起来。
由于Adapter与AdapteeXXX是委派关系,这决定了这个适配器模式是对象的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口,这里为ISerTarget接口。
源(Adaptee)角色:需要适配的类,这里为AdapteeXML,AdapteeSoap,AdapteeBin类。
适配器(Adapter)角色:通过在内部包装(Wrap)Adaptee对象,把源接口转换成目标接口。

以上的例子主要为将Person类串行化为不同的形式的例子,这里分别保存为xml,soap,binary形式。由于我们使用了Adapter进行了统一封装,这样用户可以不必知道具体的封装细节,运用统一的CreateFile方法即可将Person类串行化为不同的形式。
具体代码(C#):

  1None.gifusing System;
  2None.gifusing System.IO;
  3None.gifusing System.Xml.Serialization;
  4None.gifusing System.Xml;
  5None.gifusing System.Runtime.Serialization.Formatters.Binary;
  6ExpandedBlockStart.gifContractedBlock.gif/**//////运行时要将System.Runtime.Serialization.Formatters.Soap.dll的引用添加到项目中
  7None.gifusing System.Runtime.Serialization.Formatters.Soap;
  8None.gif
  9None.gifnamespace AdapterObject
 10ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 11ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 12InBlock.gif    ///============== Program Description==============
 13InBlock.gif    ///Name:AdapterObject.cs
 14InBlock.gif    ///Objective:AdapterObject 
 15InBlock.gif    ///Date:2006-05-04 
 16InBlock.gif    ///Written By coffee.liu
 17InBlock.gif    ///================================================
 18ExpandedSubBlockEnd.gif    /// </summary>

 19InBlock.gif    class Class1
 20ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 21InBlock.gif        [STAThread]
 22InBlock.gif        static void Main(string[] args)
 23ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 24InBlock.gif            ISerTarget target=new Adapter("XML");
 25InBlock.gif            target.CreateFile();
 26InBlock.gif            Console.WriteLine("XML file created");
 27InBlock.gif
 28InBlock.gif            target=new Adapter("Soap");
 29InBlock.gif            target.CreateFile();
 30InBlock.gif            Console.WriteLine("Soap file created");
 31InBlock.gif
 32InBlock.gif            target=new Adapter("Bin");
 33InBlock.gif            target.CreateFile();
 34InBlock.gif            Console.WriteLine("Bin file created");
 35ExpandedSubBlockEnd.gif        }

 36ExpandedSubBlockEnd.gif    }

 37InBlock.gif    [Serializable]
 38ExpandedSubBlockStart.gifContractedSubBlock.gif    public class Persondot.gif{
 39InBlock.gif        public string Name;
 40InBlock.gif        public string Sex;
 41InBlock.gif        public DateTime Brith;
 42InBlock.gif        private int PersonID;
 43InBlock.gif        public Person()
 44ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{}
 45InBlock.gif        public void SetID(int ID)
 46ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{PersonID=ID;}
 47ExpandedSubBlockEnd.gif    }

 48InBlock.gif
 49ExpandedSubBlockStart.gifContractedSubBlock.gif    interface ISerTargetdot.gif{
 50InBlock.gif        void CreateFile();
 51ExpandedSubBlockEnd.gif    }

 52ExpandedSubBlockStart.gifContractedSubBlock.gif    class Adapter:ISerTargetdot.gif{
 53InBlock.gif       private AdapteeXML aXML;
 54InBlock.gif       private AdapteeSoap aSoap;
 55InBlock.gif       private AdapteeBin aBin;
 56InBlock.gif       private string S;
 57ExpandedSubBlockStart.gifContractedSubBlock.gif        public Adapter(string s)dot.gif{
 58InBlock.gif            S=s;
 59InBlock.gif            if (s=="XML")
 60ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 61InBlock.gif                aXML=new AdapteeXML();
 62InBlock.gif                aXML.FillData();
 63ExpandedSubBlockEnd.gif            }

 64InBlock.gif            else
 65InBlock.gif                if (s=="Soap")
 66ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 67InBlock.gif                aSoap=new AdapteeSoap();
 68InBlock.gif                aSoap.FillData();
 69ExpandedSubBlockEnd.gif            }

 70InBlock.gif            else if (s=="Bin")
 71ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 72InBlock.gif                aBin=new AdapteeBin();
 73InBlock.gif                aBin.FillData();
 74ExpandedSubBlockEnd.gif            }

 75InBlock.gif            else
 76ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 77InBlock.gif                aXML=new AdapteeXML();
 78InBlock.gif                aXML.FillData();
 79ExpandedSubBlockEnd.gif            }

 80ExpandedSubBlockEnd.gif        }

 81InBlock.gif
 82ExpandedSubBlockStart.gifContractedSubBlock.gif      public  void CreateFile()dot.gif{
 83InBlock.gif          if (S=="XML")
 84ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 85InBlock.gif              aXML.CreateXMLFile();
 86ExpandedSubBlockEnd.gif          }

 87InBlock.gif          else
 88InBlock.gif              if (S=="Soap")
 89ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 90InBlock.gif              aSoap.CreateSoapFile();
 91ExpandedSubBlockEnd.gif          }

 92InBlock.gif          else if (S=="Bin")
 93ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 94InBlock.gif              aBin.CreateBinFile();
 95ExpandedSubBlockEnd.gif          }

 96InBlock.gif          else
 97ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 98InBlock.gif              aXML.CreateXMLFile();
 99ExpandedSubBlockEnd.gif          }
 
100InBlock.gif      
101ExpandedSubBlockEnd.gif      }

102InBlock.gif    
103ExpandedSubBlockEnd.gif    }

104ExpandedSubBlockStart.gifContractedSubBlock.gif    class AdapteeSoapdot.gif{
105InBlock.gif      FileStream aFileSoap;
106InBlock.gif        Person aPerson;
107InBlock.gif        SoapFormatter aSoapFormatter;
108ExpandedSubBlockStart.gifContractedSubBlock.gif        public AdapteeSoap()dot.gif{
109InBlock.gif          aSoapFormatter=new SoapFormatter();
110InBlock.gif            aPerson=new Person();
111ExpandedSubBlockEnd.gif        }

112InBlock.gif        public void FillData()
113ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
114InBlock.gif            aPerson.Name="Soap";
115InBlock.gif            aPerson.Sex="";
116InBlock.gif            aPerson.Brith=DateTime.Now;
117InBlock.gif            aPerson.SetID(2);
118ExpandedSubBlockEnd.gif        }

119ExpandedSubBlockStart.gifContractedSubBlock.gif        public void CreateSoapFile()dot.gif{
120InBlock.gif            try
121ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
122InBlock.gif                aFileSoap=new FileStream("SoapPerson.xml",FileMode.OpenOrCreate);
123InBlock.gif                aSoapFormatter.Serialize(aFileSoap,aPerson);
124InBlock.gif                aFileSoap.Close();
125ExpandedSubBlockEnd.gif            }

126ExpandedSubBlockStart.gifContractedSubBlock.gif            catch(IOException e)dot.gif{
127InBlock.gif              Console.WriteLine("some error happened");
128InBlock.gif                Console.WriteLine(e.ToString());
129InBlock.gif                return;
130ExpandedSubBlockEnd.gif            }

131InBlock.gif
132ExpandedSubBlockEnd.gif        }

133ExpandedSubBlockEnd.gif    }

134InBlock.gif    class AdapteeBin
135ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
136InBlock.gif        FileStream aFileBin;
137InBlock.gif        Person aPerson;
138InBlock.gif        BinaryFormatter aBinaryFormatter;
139InBlock.gif        public AdapteeBin()
140ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
141InBlock.gif            aBinaryFormatter=new BinaryFormatter();
142InBlock.gif            aPerson=new Person();
143ExpandedSubBlockEnd.gif        }

144InBlock.gif        public void FillData()
145ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
146InBlock.gif            aPerson.Name="Bin";
147InBlock.gif            aPerson.Sex="";
148InBlock.gif            aPerson.Brith=DateTime.Now;
149InBlock.gif            aPerson.SetID(3);
150ExpandedSubBlockEnd.gif        }

151InBlock.gif        public void CreateBinFile()
152ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
153InBlock.gif            try
154ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
155InBlock.gif                aFileBin=new FileStream("BinPerson.data",FileMode.OpenOrCreate);
156InBlock.gif                aBinaryFormatter.Serialize(aFileBin,aPerson);
157InBlock.gif                aFileBin.Close();
158ExpandedSubBlockEnd.gif            }

159InBlock.gif            catch(IOException e)
160ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
161InBlock.gif                Console.WriteLine("some error happened");
162InBlock.gif                Console.WriteLine(e.ToString());
163InBlock.gif                return;
164ExpandedSubBlockEnd.gif            }

165InBlock.gif
166ExpandedSubBlockEnd.gif        }

167ExpandedSubBlockEnd.gif    }

168ExpandedSubBlockStart.gifContractedSubBlock.gif    class AdapteeXMLdot.gif{
169InBlock.gif        FileStream aFile;
170InBlock.gif        Person aPerson;
171InBlock.gif        XmlSerializer aXML;
172ExpandedSubBlockStart.gifContractedSubBlock.gif        public AdapteeXML()dot.gif{
173InBlock.gif         aXML=new XmlSerializer(typeof(Person));
174InBlock.gif            aPerson=new Person();
175ExpandedSubBlockEnd.gif    }

176ExpandedSubBlockStart.gifContractedSubBlock.gif        public void FillData()dot.gif{
177InBlock.gif        aPerson.Name="XML";
178InBlock.gif            aPerson.Sex="";
179InBlock.gif            aPerson.Brith=DateTime.Now;
180InBlock.gif            aPerson.SetID(1);
181ExpandedSubBlockEnd.gif        }

182ExpandedSubBlockStart.gifContractedSubBlock.gif        public void CreateXMLFile()dot.gif{
183InBlock.gif            try
184ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
185InBlock.gif                aFile=new FileStream("Person.xml",FileMode.Create);
186ExpandedSubBlockEnd.gif            }

187InBlock.gif            catch(IOException e)
188ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
189InBlock.gif             Console.WriteLine("some error happened!");
190InBlock.gif                Console.WriteLine(e.ToString());
191InBlock.gif                return;
192ExpandedSubBlockEnd.gif            }

193InBlock.gif            aXML.Serialize(aFile,aPerson);
194InBlock.gif            aFile.Close();
195ExpandedSubBlockEnd.gif        }

196ExpandedSubBlockEnd.gif    }

197ExpandedBlockEnd.gif}

198None.gif

类适配器和对象适配器之间的差别:
   1.当我们想匹配一个类和它所有子类时,类适配器将不能胜任,因为在创建子类时就已定义了派生它的基类。如上第二例,要想改为类适配器模式就必须使用三个Adapter来分别封装三个Adaptee,这样做不太实际。
   2.类适配器允许适配器更改某些被匹配的类的方法,同时还允许使用其他未修改的方法。
   3. 对象适配器通过将子类传递给构造函数而允许匹配所有子类,如上面的第二例。
   4.对象适配器要求读者将希望使用的,被匹配对象的方法提到表面上来。

转载于:https://www.cnblogs.com/coffeeliu/archive/2006/05/04/391410.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值