1、定义
将一个类的接口转换成客户所希望的另一个接口。adapter模式使得原本由于接口不兼容而不能在一起工作的类可以一起工作。
2、结构
对象适配器依赖于对象组合
3、协作角色
Target:供客户断掉用的接口
Adapter: 适配Target和Adaptee
Adaptee:已经存在的接口
4、适用性
想使用一个已存在的库,但是接口不兼容
5、实例:
1、需求,现在已存在一个画图的库,但是另外一个套UI接口不匹配,需要写一个adapter将他们适配到一起。
2、实现,选其中一个画线的函数做示例
common.h
#ifndef __COMMON_H__
#define __COMMON_H__
#define RET_SUCCESS 0
#define RET_FAIL (-1)
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef struct
{
WORD x1;
WORD y1;
WORD x2;
WORD y2;
}RECT;
typedef struct {
WORD Width;
WORD Height;
char *data;
}bitmap, *pbitmap;
typedef struct
{
void (*draw_line_16bit)(WORD x1, WORD y1, WORD x2, WORD y2, WORD color,bitmap *gbitmap);
void (*draw_line_32bit)(WORD x1, WORD y1, WORD x2, WORD y2, DWORD color,bitmap *gbitmap);
}iAdapatee;
#endif
adaptee.h
#ifndef __ADAPTEE_H__
#define __ADAPTEE_H__
void draw_line_16bit(WORD x1, WORD y1, WORD x2, WORD y2, WORD color,bitmap *gbitmap);
void draw_line_32bit(WORD x1, WORD y1, WORD x2, WORD y2, DWORD color,bitmap *gbitmap);
#endif
adaptee.c
#include <stdio.h>
#include "common.h"
#include "adaptee.h"
WORD Abs(WORD x)
{
if(x < 0) return (-x);
return x;
}
void draw_line_16bit(WORD x1, WORD y1, WORD x2, WORD y2, WORD color,bitmap *gbitmap)
{
int i,p,n,x,y,tn;
WORD *ptr;
if(y1 == y2) //horiziontal line
{
if(x1 > x2) { x=x2; x2=x1; x1=x; }
if(x1 >= gbitmap->Width)
return;
if(x2 >= gbitmap->Width)
x2 = gbitmap->Width-1;
ptr = (WORD *)gbitmap->data;
ptr += y1*gbitmap->Width+x1;
for(i=x1; i<x2; i++)
*ptr++ = color;
return;
}
if(x1 == x2) //vertical line
{
if(y1 > y2) { y=y2; y2=y1; y1=y; }
if(y1 >= gbitmap->Height)
return;
if(y2 >= gbitmap->Height)
y2 = gbitmap->Height-1;
ptr = (WORD *)gbitmap->data;
ptr += y1*gbitmap->Width+x1;
for(i=0;i<(y2-y1);i++)
{
*ptr = color;
ptr += gbitmap->Width;
}
return;
}
if(Abs(y2-y1) <= Abs(x2-x1))
{
if(((y2<y1) && (x2<x1)) || ((y1<=y2) && (x1>x2)))
{
x=x2; y=y2; x2=x1; y2=y1; x1=x; y1=y;
}
if((y2>=y1) && (x2>=x1))
{
x=x2-x1; y=y2-y1;
p=2*y; n=2*x-2*y; tn=x;
ptr = (WORD *)gbitmap->data;
ptr += y1*gbitmap->Width;
while(x1<=x2)
{
if(tn >= 0) tn-=p;
else { tn+=n; y1++; ptr+=gbitmap->Width; }
*(ptr+x1++) = color;
}
}
else
{
x=x2-x1; y=y2-y1;
p=-2*y; n=2*x+2*y; tn=x;
ptr = (WORD *)gbitmap->data;
ptr += y1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1--; ptr-=gbitmap->Width; }
*(ptr+x1++) = color;
}
}
}
else
{
x=x1; x1=y2; y2=x; y=y1; y1=x2; x2=y;
if(((y2<y1) && (x2<x1)) || ((y1<=y2) && (x1>x2)))
{
x=x2; y=y2; x2=x1; y2=y1; x1=x; y1=y;
}
if((y2>=y1) && (x2>=x1))
{
x=x2-x1; y=y2-y1; p=2*y; n=2*x-2*y; tn=x;
ptr = (WORD *)gbitmap->data;
ptr += x1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1++; }
*(ptr+y1) = color;
ptr += gbitmap->Width;
x1++;
}
}
else
{
x=x2-x1; y=y2-y1; p=-2*y; n=2*x+2*y; tn=x;
ptr = (WORD *)gbitmap->data;
ptr += x1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1--; }
*(ptr+y1) = color;
ptr += gbitmap->Width;
x1++;
}
}
}
}
void draw_line_32bit(WORD x1, WORD y1, WORD x2, WORD y2, DWORD color,bitmap *gbitmap)
{
int i,p,n,x,y,tn;
DWORD *ptr;
if(y1 == y2) //horiziontal line
{
if(x1 > x2) { x=x2; x2=x1; x1=x; }
if(x1 >= gbitmap->Width)
return;
if(x2 >= gbitmap->Width)
x2 = gbitmap->Width-1;
ptr = (DWORD *)gbitmap->data;
ptr += y1*gbitmap->Width+x1;
for(i=x1; i<x2; i++)
*ptr++ = color;
return;
}
if(x1 == x2) //vertical line
{
if(y1 > y2) { y=y2; y2=y1; y1=y; }
if(y1 >= gbitmap->Height)
return;
if(y2 >= gbitmap->Height)
y2 = gbitmap->Height-1;
ptr = (DWORD *)gbitmap->data;
ptr += y1*gbitmap->Width+x1;
for(i=0;i<(y2-y1);i++)
{
*ptr = color;
ptr += gbitmap->Width;
}
return;
}
if(Abs(y2-y1) <= Abs(x2-x1))
{
if(((y2<y1) && (x2<x1)) || ((y1<=y2) && (x1>x2)))
{
x=x2; y=y2; x2=x1; y2=y1; x1=x; y1=y;
}
if((y2>=y1) && (x2>=x1))
{
x=x2-x1; y=y2-y1;
p=2*y; n=2*x-2*y; tn=x;
ptr = (DWORD *)gbitmap->data;
ptr += y1*gbitmap->Width;
while(x1<=x2)
{
if(tn >= 0) tn-=p;
else { tn+=n; y1++; ptr+=gbitmap->Width; }
*(ptr+x1++) = color;
}
}
else
{
x=x2-x1; y=y2-y1;
p=-2*y; n=2*x+2*y; tn=x;
ptr = (DWORD *)gbitmap->data;
ptr += y1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1--; ptr-=gbitmap->Width; }
*(ptr+x1++) = color;
}
}
}
else
{
x=x1; x1=y2; y2=x; y=y1; y1=x2; x2=y;
if(((y2<y1) && (x2<x1)) || ((y1<=y2) && (x1>x2)))
{
x=x2; y=y2; x2=x1; y2=y1; x1=x; y1=y;
}
if((y2>=y1) && (x2>=x1))
{
x=x2-x1; y=y2-y1; p=2*y; n=2*x-2*y; tn=x;
ptr = (DWORD *)gbitmap->data;
ptr += x1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1++; }
*(ptr+y1) = color;
ptr += gbitmap->Width;
x1++;
}
}
else
{
x=x2-x1; y=y2-y1; p=-2*y; n=2*x+2*y; tn=x;
ptr = (DWORD *)gbitmap->data;
ptr += x1*gbitmap->Width;
while(x1<=x2)
{
if(tn>=0) tn-=p;
else { tn+=n; y1--; }
*(ptr+y1) = color;
ptr += gbitmap->Width;
x1++;
}
}
}
}
adapter.c
#include <stdio.h>
#include "common.h"
#include "adaptee.h"
#include "target.h"
iAdapatee g_Fuc = {NULL, NULL};
int adapter_init()
{
g_Fuc.draw_line_16bit = draw_line_16bit;
g_Fuc.draw_line_32bit = draw_line_32bit;
}
int drawline16(RECT *rect, WORD color,bitmap *gbitmap)
{
WORD x1, y1, x2, y2;
x1 = rect->x1;
x2 = rect->x2;
y1 = rect->y1;
y2 = rect->y2;
if(g_Fuc.draw_line_16bit)
g_Fuc.draw_line_16bit(x1, y1, x2, y2, color, gbitmap);
else
return RET_FAIL;
return RET_SUCCESS;
}
int drawline32(RECT *rect, DWORD color,bitmap *gbitmap)
{
WORD x1, y1, x2, y2;
x1 = rect->x1;
x2 = rect->x2;
y1 = rect->y1;
y2 = rect->y2;
if(g_Fuc.draw_line_32bit)
g_Fuc.draw_line_32bit(x1, y1, x2, y2, color, gbitmap);
else
return RET_FAIL;
return RET_SUCCESS;
}
target.h
#ifndef __TARGET_H__
#define __TARGET_H__
int adapter_init();
int drawline16(RECT *rect, WORD color,bitmap *gbitmap);
int drawline32(RECT *rect, DWORD color,bitmap *gbitmap);
#endif
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "target.h"
void main()
{
RECT rect;
bitmap gbitmap;
unsigned int i,j;
gbitmap.Width = 32;
gbitmap.Height = 18;
char *pwdata;
char *pdwdata;
WORD wcolor = ('*' << 8)|'*';
DWORD dwcolor = ('*' << 24)|('*' << 16)|('*' << 8)|'*';
//test 16bit
adapter_init();
rect.x1 = 5;
rect.y1 = 6;
rect.x2 = 3;
rect.y2 = 10;
gbitmap.data = malloc(gbitmap.Width*gbitmap.Height*2);
memset((void *)gbitmap.data, 0, gbitmap.Width*gbitmap.Height*2);
drawline16(&rect, wcolor, &gbitmap);
pwdata = (char *)gbitmap.data;
for(i = 0; i < gbitmap.Height; i++)
{
for(j = 0; j < gbitmap.Width*2; j++)
{
printf("%c ",*pwdata++);
}
printf("\n");
}
free(gbitmap.data);
//test 32bit
gbitmap.data = malloc(gbitmap.Width*gbitmap.Height*4);
memset((void *)gbitmap.data, 0, gbitmap.Width*gbitmap.Height*4);
drawline32(&rect, dwcolor, &gbitmap);
pdwdata = (char *)gbitmap.data;
for(i = 0; i < gbitmap.Height; i++)
{
for(j = 0; j < gbitmap.Width*4; j++)
{
printf("%c ",*pdwdata++);
}
printf("\n");
}
free(gbitmap.data);
}