装饰模式学习笔记

来源:互联网 发布:淘宝网iphone版 编辑:程序博客网 时间:2024/06/11 10:18

装饰模式

装饰模式的定义动态地给一个对象添加额外的职责,就添加功能来说,装饰模式比生成子类更加灵活。

这段话比较抽象,自己根据装饰模式实践了一下,有了一些小小的领悟分享一下。

我们最开始有一抽象类,比如说是人,它有两个子类分别是学生和老师,并且有一些共有的属性放在抽象类“人”中,有一些独有的属性放在各自的学生类和老师类中。并且有一个虚函数要学生和老师类来实现。
这模拟的是我们已经有一个生态系统了。

Person类:

public abstract class Person{    public String name = "";    public int age  = 0;    public abstract void show();}

Student类:

public class Student extends Person {    private int grade = 0;    public Student(String name, int age, int grade) {        this.name = name;        this.age = age;        this.grade = grade;    }    @Override    public void show() {        System.out.println("Student "+name+"'s age is "+age+" in grade "+grade);    }}

teacher类:

public class Teacher extends Person {    public Teacher(String name, int age) {        this.name = name;        this.age  = age;    }    @Override    public void show() {        System.out.println("Teacher "+name+"'s age is "+age);    }}

现在我们需要向Person添加一个功能,给每个人穿衣服并且显示每个人的穿着。

在Person类中添加一个虚函数,再在各个类中实现穿衣这个穿衣函数,但是这种方法即难以实现又违背了开闭原则,因为会去更改每个类。

装饰模式提供了一种很好的解决方案:
定义一个接口,我的理解是定义一个需要添加的功能的接口,比如此种情况,我们定义一个Dress接口:

public interface Dress {    public void dressing();}

然后先对这个接口编写各种衣服的类,所以先抽象出来一个衣物类Finary,它实现了接口。Finary的构造函数很重要,它指定需要装饰哪个对象的Dress接口

public class Finery implements Dress {    private Dress dress = null;    public Finery(Dress dress) {        this.dress = dress;    }    @Override    public void dressing() {        if(null != dress) {            dress.dressing();            System.out.println("Dressing:");        }    }}

然后创建各项衣物类Finary的子类比如Tshirt、suit、tie。。。类

public class TShirt extends Finery{    public TShirt(Dress dress) {        super(dress);    }    @Override    public void dressing() {        super.dressing();        System.out.println("TShirt");    }}
public class WearSuit extends Finery {    public WearSuit(Dress dress) {        super(dress);    }    @Override    public void dressing() {        super.dressing();        System.out.println("WearSuit");    }}
public class WearTie extends Finery{    public WearTie(Dress dress) {        super(dress);    }    @Override    public void dressing() {        super.dressing();        System.out.println("WearTie");    }}

然后是Person针对接口编程,因为每个人都需要穿衣服,并且都需要穿内衣……

public abstract class Person implements Dress{    public String name = "";    public int age  = 0;    @Override    public void dressing() {        System.out.println("Dressing: UnderWear");    }    public abstract void show();}

对于student和teacher类这里不需要重写dressing(),这是装饰模式最重要的应用点!!!即不需要修改已经实例化的Person子类,只需要抽象类Person针对接口编程,符合开闭原则,完美啊!!!

最后来看下是怎么调用的:

 public static void main(String[] args) {        Person person = new Student("peter",15,2);        person.show();        Dress studentDress = person;        studentDress = new TShirt(studentDress);        studentDress = new BigTrousers(studentDress);        studentDress.dressing();        person = new Teacher("jobey",35);        person.show();        Dress teacherDress = person;        teacherDress = new WearSuit(teacherDress);        teacherDress = new WearTie(teacherDress);        teacherDress.dressing();    }

我们new一个student的时候,不仅实例化了一个学生对象,并且也实现了一个Dress接口,原来student的内容不需要改,要给每个学生穿衣服只需要将person的Dress接口提取出来:

Dress studentDress = person;

然后对person的Dress接口“穿衣服”就行了!!!
此处就是对实例化了的stduent的Dress接口studentDress进行“穿衣服”:

studentDress = new TShirt(studentDress);studentDress = new BigTrousers(studentDress);studentDress.dressing();

输出结果:

Student peter's age is 15 in grade 2Dressing: UnderWearDressing: TShirtDressing: BigTrousersTeacher jobey's age is 35Dressing: UnderWearDressing: WearSuitDressing: WearTie
studentDress.dressing();

首先调用的是Person实现的dressing(),我的理解是毕竟这是new person才创建的接口嘛,之后是按“穿衣”顺序来调用dressing()函数。

0 0
原创粉丝点击