装饰模式学习笔记

装饰模式

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

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

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

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 2
Dressing: UnderWear
Dressing: TShirt
Dressing: BigTrousers
Teacher jobey's age is 35
Dressing: UnderWear
Dressing: WearSuit
Dressing: WearTie
studentDress.dressing();

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值