写在前面
今天学习的是装饰者模式
那么什么是装饰模式呢?
装饰模式: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活
一、具体问题
搭建一个可以给人搭配不同服饰的穿衣系统,比如类似QQ秀或者厘米秀,QQ飞车人物装饰,你会怎么设计???
直接写在一个类里??
如果像上面的方式的话,确实可以实现功能【就是把穿各种衣服的方法写在这个人的类里】,但是这样耦合度太高,而且后期需要添加其他的装饰功能的话,就会更改Person,这不符合开放——封闭原则【对扩展开发,对修改关闭】
那使用继承呢?
确实也可以实现功能,但是你这好像是一件一件的穿衣服,好比你光着身子,当着大家的面,先穿T恤,再穿裤子,仿佛在跳穿衣舞,所以你需要将他们在内部就组装好/穿好【加一层】,听起来是不是有点像建造者模式??,但是这不是建造者模式,因为建造者模式的建造过程要求是稳定的,显然我们的穿衣过程是不稳定的【因为穿衣组合有无数种】
二、使用装饰者模式解决问题
Person
package com.fafa.designmode.decorator;
/**
* 被装饰者
*
* @author Sire
* @version 1.0
* @date 2022-03-08 22:51
*/
public class Person {
public Person() {
}
private String name;
public Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
Finery
package com.fafa.designmode.decorator;
/**
* 装饰类
*
* @author Sire
* @version 1.0
* @date 2022-03-08 23:00
*/
public class Finery extends Person {
protected Person component;
/**
* 打扮
*
* @param component
*/
public void Decorate(Person component) {
this.component = component;
}
@Override
public void show() {
if (null != component) {
component.show();
}
}
}
衣服
package com.fafa.designmode.decorator.clothes;
import com.fafa.designmode.decorator.Finery;
/**
* 垮裤
*
* @author Sire
* @version 1.0
* @date 2022-03-08 23:06
*/
public class BigTrouser extends Finery {
@Override
public void show() {
System.out.println("垮裤");
super.show();
}
}
package com.fafa.designmode.decorator.clothes;
import com.fafa.designmode.decorator.Finery;
/**
* @author Sire
* @version 1.0
* @date 2022-03-08 23:22
*/
public class Sneakers extends Finery {
@Override
public void show() {
System.out.println("破球鞋");
super.show();
}
}
package com.fafa.designmode.decorator.clothes;
import com.fafa.designmode.decorator.Finery;
/**
* @author Sire
* @version 1.0
* @date 2022-03-09 0:16
*/
public class Tie extends Finery {
@Override
public void show() {
System.out.println("打领带");
super.show();
}
}
package com.fafa.designmode.decorator.clothes;
import com.fafa.designmode.decorator.Finery;
/**
* 大T恤
*
* @author Sire
* @version 1.0
* @date 2022-03-08 23:02
*/
public class TShirts extends Finery {
@Override
public void show() {
System.out.println("大T恤");
super.show();
}
}
客戶端
package com.fafa.designmode.decorator;
import com.fafa.designmode.decorator.clothes.BigTrouser;
import com.fafa.designmode.decorator.clothes.Sneakers;
import com.fafa.designmode.decorator.clothes.TShirts;
import com.fafa.designmode.decorator.clothes.Tie;
/**
* 客户端
*
* @author Sire
* @version 1.0
* @date 2022-03-08 23:26
*/
public class DecoratorClient {
public static void main(String[] args) {
Person person = new Person("可爱发");
System.out.println("第一种装扮");
// 装饰对象
Sneakers sneakers = new Sneakers();
BigTrouser bigTrouser = new BigTrouser();
TShirts tShirts = new TShirts();
Tie tie = new Tie();
// 装饰过程【顺序很重要】
sneakers.Decorate(person);
bigTrouser.Decorate(sneakers);
tShirts.Decorate(bigTrouser);
tie.Decorate(tShirts);
// 展示
tie.show();
}
}
运行结果
三、总结
从以上,我们可以知道,当我们使用继承,导致子类膨胀,我们不想增加很多子类的情况下,将具体功能职责划分,同时继承装饰者超类,动态地给一个对象添加一些额外的职责便实现了我们的装饰者模式。
优缺点
1、优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
2、缺点:多层装饰比较复杂。
使用场景
1、扩展一个类的功能。
2、动态增加功能,动态撤销。
实际使用:这里我们说一下,在java中I/O便使用了装饰者模式。
装饰者用到的设计原则
1、多用组合,少用继承。
2、对扩展开放,对修改关闭。