一直的想写该模式,可是,没怎么时间去弄,也就把别人写的例子或者书上的例子从新写下.
适配器模式概述:
由于我的工作经常的是对集团软件的二次开发,因此,很多的时候会碰到这样的情况.
及经常的需要用到原有系统的一些对象或者接口,但是,二次开发过程中,所用到的新接口又不是这些现有对象或者接口所不满足的,解决这个问题,也就可以用到本模式了.
目的或者意图:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作(引用别人的话.)
例子:
<java与模式>书上讲的 指鹿为马,指方为圆
本篇以日志记录来解说;
原有系统,有这样的日志记录接口:
IOldLog
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public interface IOldLog
{
void OldLogWrite();
}
}
而现阶段却需要用的是这样的日志记录接口:
INewLog
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public interface INewLog
{
void NewLogWrite();
}
}
同时,有两种新的日志记录方法:
1:数据库方式:
DatabaseLog
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class DatabaseLog:INewLog
{
public void NewLogWrite()
{
Console.WriteLine("this is new logWrite of Database");
}
}
}
2:文件记录方式
FileLog
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class FileLog : INewLog
{
public void NewLogWrite()
{
Console.WriteLine("this is new logWrite of File");
}
}
}
而由于我们需要是这样的使用:
既:
Code
IOldLog databaseLog = new DatabaseLog();
databaseLog.OldLogWrite();//既我们需要使用这个OldLogWrite()方法
显然,上面的代码现在不能够编译通过.
因此,我们需要有个数据库的适配类,继承
DatabaseLog, IOldLog.
DatabaseLogAdapter
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class DatabaseLogAdapter : DatabaseLog, IOldLog
{
public void OldLogWrite()
{
this.NewLogWrite();
}
}
}
对于文件方式:
FileLogAdapter
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class FileLogAdapter:FileLog,IOldLog
{
public void OldLogWrite()
{
this.NewLogWrite();
}
}
}
这样,我们就可以这样使用了:
Code
IOldLog OldLog = new DatabaseLogAdapter();
OldLog.OldLogWrite();
这样,也就做到了用原来的接口,而使用的是新的方法.
但是,这样的做法,也存在一些问题.
1:对于现阶段的记录方式,有数据库,文件两钟方式,对于以后新增加一种方式,如短信通知,虽然,我们可以很容易的加入一个短信日志的类和其对应的适配器,但是,这样却造成了类的数量上的增加.
2:同时,由于这样的做法是用多继承来满足的,至少是增加了各个类之间的偶合度.
3:同样的,由于是继承的方式得到的适配类,如数据库适配类,它不仅有了
DatabaseLog的行为,还有
IOrderLog的行为,显然,这样违背了面向对象原则的类的单一性原则.
我们可以这样的考虑,由于数据库记录方式和文件记录方式,都是继承自新的日志接口
INewLog,他们之间仅仅不同的是日志的写法上.
按照 设计模式中的 合成/聚合 原则,我们可以采用对象组合而不用采用继承来达到这样的效果.
LogAdapter
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class LogAdapter : IOldLog
{
INewLog mNewLog;
public LogAdapter(INewLog newLog)
{
this.mNewLog = newLog;
}
public void OldLogWrite()
{
mNewLog.NewLogWrite();
}
}
}
显然,这样做,至少是减少了各种记录方式的适配类了.
使用介绍:
Code
IOldLog OldLog = new LogAdapter(new DatabaseLog());
OldLog.OldLogWrite();
这种方式,有个词语叫
旧瓶装新药.
<java与模式>一书上讲的似乎是这样的.
系统原有这样的日志记录类:
OldLog
using System;
using System.Collections.Generic;
using System.Text;
namespace 适配器模式
{
public class OldLog
{
public void WirteLog()
{
Console.WriteLine("this is OldLog");
}
}
}
现在新的系统,有一个新的日志记录接口
INewLog
using System;
using System.Collections.Geniric;
using System.Text;
namespace 适配器模式
{
public interface INewLog
{
public void WirteLog();
public void PrintLog();
}
}
因此,需要有一个适配类,来把原有的日子记录方法,适配到现有接口中:
LogAdapter
using System;
using System.Collection.Genric;
using System.Text;
namespace 适配器模式
{
public class LogAdapter:INewLog
{
private OldLog mOldLog;
public LogAdapter(OldLog oldLog)
{
this.mOldLog=oldLog;
}
//实现接口的方法
public void WirteLog()
{
this.mOldLog.WirteLog();
}
public void PrintLog()
{
Console.WriteLine("this is newLog's printLog");
}
}
}
使用起来,应该是这样的:
Code
INewLog newLog= new LogAdapter(new OldLog());
newLog.WirteLog();
这样的情况,叫
新瓶装旧药,同时,有可能会误认为适配器模式是为了增加新的功能,就如上面的PrintLog(),其实不然,其真正作用还是在功能相近或者相同的方法的转换使用上。
对于本模式的其他的好处或者注意要点,可以参考别人的文章:
适配器模式