适配器模式(Adapter Pattern)
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作,现实中适配器的例子有很多,这种模式很好理解。值得注意的是适配器模式总是在系统扩展时使用,如果前期设计时能够预见到这些变化,可以用其他的模式(如桥接模式)避免。
下例以一个Arraylist实现栈结构来模拟适配器模式(严格的说是对象适配器模式)的使用场景,其中
IAdapter = Target
StackAdapter = Adapter
ArrayList = Adaptee
图1:类适配器模式结构图
图2:对象适配器模式结构图
public class App
{
public static void Main()
{
StackAdapter stack = new StackAdapter();
stack.Push(3);
stack.Push(2);
stack.Push(1);
stack.Pop();
stack.Pop();
stack.Pop();
}
}
public interface IAdapter
{
void Push(object item);
object Pop();
object Peek();
}
public class StackAdapter : IAdapter
{
ArrayList list;
public StackAdapter()
{
list = new ArrayList();
}
public void Push(object item)
{
list.Add(item);
}
public object Pop()
{
object o = this.Peek();
if (list.Count > 0)
list.RemoveAt(list.Count - 1);
else
throw new InvalidOperationException("栈为空");
return o;
}
public object Peek()
{
if (list.Count > 0)
return list[list.Count - 1];
else
throw new InvalidOperationException("栈为空");
}
}
{
public static void Main()
{
StackAdapter stack = new StackAdapter();
stack.Push(3);
stack.Push(2);
stack.Push(1);
stack.Pop();
stack.Pop();
stack.Pop();
}
}
public interface IAdapter
{
void Push(object item);
object Pop();
object Peek();
}
public class StackAdapter : IAdapter
{
ArrayList list;
public StackAdapter()
{
list = new ArrayList();
}
public void Push(object item)
{
list.Add(item);
}
public object Pop()
{
object o = this.Peek();
if (list.Count > 0)
list.RemoveAt(list.Count - 1);
else
throw new InvalidOperationException("栈为空");
return o;
}
public object Peek()
{
if (list.Count > 0)
return list[list.Count - 1];
else
throw new InvalidOperationException("栈为空");
}
}
适配器模式也有许多版本
如在ADO.NET中经常使用的DbDataAdapter, 其中需要指定适配器(DbDataAdapter)的适配对象(DataSet)和被适配对象(DbCommand)
DbDataAdapter adapter = new SqlDataAdapter(dbcommand);
DataSet ds = new DataSet();
adapter.Fill(ds);
DataSet ds = new DataSet();
adapter.Fill(ds);
还有更灵活的适配器,如Array.Sort,只要指定被适配对象(需要排序的数据)和适配规则(实现IComparer接口的类)就可以返回适配对象(排好序的数组)。
public class App
{
public static void Main()
{
PersonComparer comparer = new PersonComparer();
Person[] persons = { new Person("zhang san", 18), new Person("li si", 20), new Person("wang wu", 15) };
Array.Sort(persons, comparer);
}
}
public class PersonComparer : IComparer<Person>
{
public int Compare(Person person1, Person person2)
{
if (person1.age == person2.age)
return 0;
else if (person1.age > person2.age)
return 1;
else
return -1;
}
}
public class Person
{
public string name { get; set; }
public int age { get; set; }
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
}
{
public static void Main()
{
PersonComparer comparer = new PersonComparer();
Person[] persons = { new Person("zhang san", 18), new Person("li si", 20), new Person("wang wu", 15) };
Array.Sort(persons, comparer);
}
}
public class PersonComparer : IComparer<Person>
{
public int Compare(Person person1, Person person2)
{
if (person1.age == person2.age)
return 0;
else if (person1.age > person2.age)
return 1;
else
return -1;
}
}
public class Person
{
public string name { get; set; }
public int age { get; set; }
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
}