今天来学习分析下装饰器模式,首先我们分析它的名字应该要知道这个模式的作用应该就是类似我们用装饰品一样,随用随取的特点。发挥你的想象,如果我们写的程序能有这样的特点,以后业务需要更改的时候是不是再也不用埋头写BUG了,只需要把不要的装饰换下来就好了,废话不多说,下面让我们看看是怎么实现装饰器模式的吧。
首先,依旧是老规矩,设定一个场景:学生购买课程课后练习巩固,首先,学生需要购买课程,然后学习课程,接着课后练习,再然后就提交作业等一系列动作;这里主体就是学生,接下来,我们就应该干嘛呢,没错,当然是抽象一个学生类出来,请看代码:
public abstract class AbstractStudent { public int Id { get; set; } public string Name { get; set; } public abstract void Study(); }
很简单,AbstractStudent类包含两个属性和一个抽象方法,这就是我们抽象出来的学生类。接下来,我们就要来创建我们今天的重头类了装饰器的基类,看代码
/// <summary> /// 装饰器的基类 /// 也是一个学员 继承了抽象类 /// </summary> public class BaseStudentDecorator : AbstractStudent { private AbstractStudent _Student = null; public BaseStudentDecorator(AbstractStudent student) { this._Student = student; } public override void Study() { this._Student.Study(); //Console.WriteLine("**********"); //基类装饰器必须是个空的行为 } }
这个装饰器基类它继承了我们开始创建的抽象学生类,所以它也是一个学生类,这个BaseStudentDecorator类有一个构造函数和重写了AbstractStudent类的Study方法,这里利用构造函数注入了一个AbstractStudent对象,然后重写了AbstractStudent抽象类的方法Study去调用它的Study,到这估计迷糊了,为什么要这样做呢,绕来绕去干嘛呢这是,不急,我们接着往下看
public class StudentVip : AbstractStudent { public override void Study() { Console.WriteLine("{0}是VIP学生,正在学习vip课程 ", base.Name); } }
这里我们创建了一个StudentVip类,它继承AbstractStudent抽象学生类,并且重写Study方法,实现自己的逻辑,到这里就结束了吗,那这个装饰器模式岂不是废柴吗(哈哈),别着急,我们接着往下看
public class StudentPreivew : BaseStudentDecorator { public StudentPreivew(AbstractStudent student) : base(student)//表示父类的构造函数 { //this._Student = student; } public override void Study() { Console.WriteLine("预习"); base.Study(); } }
这里就开始变化了,我们创建了一个StudentPreivew类,注意,它实现的是BaseStudentDecorator类,同样它重写Study方法,这样,我们就实现了装饰器模式了,??什么,这就实现了,我还没有明白是怎么回事呢,搞什么呢。。。所有的骨架我们基本都学完了,现在就让我们看看上端是如何调用实现装饰的
class Program { static void Main(string[] args) { try { Console.WriteLine("--------------------------"); AbstractStudent abstractStudent = new StudentVip() { Id = 9, Name = "jjjj" }; Console.WriteLine("*************************"); { abstractStudent = new StudentPreivew(abstractStudent);//预习
abstractStudent.Study();
} } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.Read(); } }
首先,我们创建一个Vip学生,给它分配号码取名字。这里有个知识点,抽象类是不能通过New关键字实例化的,接口也是一样,知识点get到了没有。接下来我们实例化了一个StudetPreivew,传入我们之前创建的AbstractStudent类,为什们呢,因为我们的构造函数需要一个AbstractStudent对象才能创建我们的StudentPreivew对象,不然是无法创建StudentPreivew对象的,现在,让我们运行程序来看看运行结果。
我们可以看到,我们成功的把预习这个动作成功的装饰上去了,如果你愿意,我们可以添加更多的动作和逻辑,如果你不愿意,只要不实例化StudentPreivew对象就可以,这样是不是就是达到了装饰的效果呢,想用的时候new它,不想用的时候不new它,注意,我们所有的操作都是在最上层修改,根本不用关心底层代码,看完这个装饰器模式,是不是有种似曾相识的感觉呢,哈哈,对,和之前说的策略模式很相像对吧,策略模式是有一个上下文类,通过上层传入需要的实际策略类,然后调用上下文类方法去实现,我们今天所说的装饰器是实例所需要的动作类传入主体,实际动作类继承BaseStudentDecorator类,而BaseStudentDecorator类又继承AbstractStudent类,最后我们上层调用的方法是AbstractStudent类的Study方法,所以,可以这么说,孙子通过父亲调用爷爷的方法,这句话就是我们今天所讲的装饰器模式的精髓(O(∩_∩)O哈哈~)。。。