适配器模式和装饰器模式

本文详细阐述了在项目迭代中如何使用适配器模式处理接口不兼容问题,并通过装饰器模式实现对Dog类的无侵入式拓展。
摘要由CSDN通过智能技术生成

一、适配器模式

使用场景:

        适配器模式用于解决项目迭代过程中,新接口与旧接口不兼容的问题。

作用:

        让旧代码能调用新接口中升级后的方法。

补充:

        新接口是旧接口的升级。新接口与旧接口中定义的方法相同,但旧接口的实现类对方法的实现较原始,而新接口的实现类对方法的实现更加高明。旧代码无法直接调用新接口提供的高级方法,称为接口不兼容。

案例:

        项目中有 ”添加用户“ 的功能点,老版本的项目定义了接口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个角色:组件、具体组件(被装饰者)、装饰器、具体装饰器。

  1. 组件是装饰器模式中的基础接口或抽象类,它声明了可以被装饰的方法,此处为鸣叫方法。
  2. 具体组件指的是将要拓展的目标类,此处为Dog类。
  3. 装饰器是一个继承组件的抽象类,装饰器依赖注入了具体组件。
  4. 具体装饰器是装饰器的实现类,因此具体装饰器也持有具体组件,且可以实现可装饰方法。在具体装饰器中编写装饰方法。实现可装饰方法时组合调用具体组件提供的方法和自身的装饰方法,实现对可装饰方法的前置、后置装饰。

装饰器模式实现代码如下:

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();
    }
}

运行结果:

装饰器模式类图:

  • 26
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值