一、适配器模式
使用场景:
适配器模式用于解决项目迭代过程中,新接口与旧接口不兼容的问题。
作用:
让旧代码能调用新接口中升级后的方法。
补充:
新接口是旧接口的升级。新接口与旧接口中定义的方法相同,但旧接口的实现类对方法的实现较原始,而新接口的实现类对方法的实现更加高明。旧代码无法直接调用新接口提供的高级方法,称为接口不兼容。
案例:
项目中有 ”添加用户“ 的功能点,老版本的项目定义了接口OldUserManageInterface及其实现类OldUserManage来实现该功能。
interface OldUserManageInterface{
void AddUser(string userName, int age);
}
public class OldUserManage : OldUserManageInterface{
public void AddUser(string userName, int age){
Console.WriteLine("直接添加用户信息");
}
}
internal class Program
{
static void Main(string[] args)
{
OldUserManageInterface oldUserManage = new OldUserManage();
oldUserManage.AddUser("独步寻花",25);
}
}
随着项目迭代,新版本项目提出新需求,在添加用户信息之前需要校验用户信息。由于旧版项目已经部署运行,直接修改旧版本的源代码不符合开闭原则。所以需要定义新的接口NewUserManageInterface及其实现类NewUserManage。
public class User
{
public string UserName { get; set; }
public int Age { get; set; }
}
interface NewUserManageInterface
{
void AddUser(User user);
}
public class NewUserManage : NewUserManageInterface
{
public void AddUser(User user)
{
Console.WriteLine("1、校验用户信息");
Console.WriteLine("2、添加用户信息");
}
}
新接口和旧接口都提供了AddUser方法。但由于新接口的AddUser方法与旧接口的AddUser方法参数不一致,所以旧项目无法直接调用新接口的方法。这种情况称为接口不兼容。
为解决接口兼容问题,让旧代码能使用新功能,可以使用适配器设计模式。
public class Adapter : OldUserManageInterface
{
NewUserManageInterface newUserManage = new NewUserManage();
public void AddUser(string userName, int age)
{
User user = new User() { UserName = userName, Age = age };
newUserManage.AddUser(user);
}
}
适配器类Adapter实现了旧接口OldUserManageInterface,同时又持有NewUserManage对象的引用,Adapter在实现AddUser方法时调用了NewUserManage对象提供的方法。最终将新旧接口兼容在一起。
internal class Program
{
static void Main(string[] args)
{
//OldUserManageInterface oldUserManage = new OldUserManage();
OldUserManageInterface oldUserManage = new Adapter();
oldUserManage.AddUser("独步寻花",25);
}
}
旧代码只需要在调用接口的位置,将旧接口的实现类改为适配器,即可调用新功能。
二、装饰器模式
现有一个Dog类,该类有一个鸣叫方法,调用鸣叫方法可以让Dog发出叫声。
如何在不修改Dog类源代码,不创建Dog派生类的前提下对Dog类进行拓展,使Dog在发出叫声前先摇尾巴?
使用装饰器模式,可以在不修改类源代码、不创建目标类的派生类的前提下对目标类的方法进行前置、后置装饰。适用于拓展不可被继承的类,如java中的 final 类、c# 中的 sealed 类。
装饰器中有4个角色:组件、具体组件(被装饰者)、装饰器、具体装饰器。
- 组件是装饰器模式中的基础接口或抽象类,它声明了可以被装饰的方法,此处为鸣叫方法。
- 具体组件指的是将要拓展的目标类,此处为Dog类。
- 装饰器是一个继承组件的抽象类,装饰器依赖注入了具体组件。
- 具体装饰器是装饰器的实现类,因此具体装饰器也持有具体组件,且可以实现可装饰方法。在具体装饰器中编写装饰方法。实现可装饰方法时组合调用具体组件提供的方法和自身的装饰方法,实现对可装饰方法的前置、后置装饰。
装饰器模式实现代码如下:
public interface Animal //组件
{
void MakeSound(); //声明可被装饰的方法
}
public class Dog : Animal //具体组件(被装饰者)
{
public virtual void MakeSound() { Console.WriteLine("汪汪"); } //定义可被装饰的方法
}
public abstract class Decrator : Animal //装饰器
{
public Animal animal = new Dog(); //持有具体组件的引用
public abstract void MakeSound();
}
public class DogDecrator : Decrator //具体装饰器
{
public void WagTail() { Console.WriteLine("摇尾巴"); } //编写装饰方法
public override void MakeSound() //实现可装饰方法
{
WagTail(); //调用自身的装饰方法
this.animal.MakeSound(); //调用具体装饰器提供的方法
}
}
internal class Program
{
static void Main(string[] args)
{
Animal dogDecrator = new DogDecrator();
dogDecrator.MakeSound();
}
}
运行结果:
装饰器模式类图: