1、装饰器模式定义
允许向一个现有的对象添加新的功能,同时又不改变其结构,属于结构型设计模式,即对先有类进行包装,在不想增加很多子类的情况下扩展类。
优点: 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点: 多层装饰比较复杂
2、具体实现方式
Component
为统一接口,也是装饰类和被装饰类的基本类型ConcreteComponent
为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。Decorator
是装饰类,实现了Component
接口的同时还在内部维护了一个ConcreteComponent
的实例,并可以通过构造函数初始化。而Decorator
本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。ConcreteDecorator
是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent
,从而对其进行装饰。
interface Component{
void method();
}
//被装饰的类 FileInputStream
class ConcreteComponent implements Component {
@Override
public void method() {
System.out.println("原先的功能");
}
}
//装饰类 FilterInputStream
abstract class Decorate implements Component{
protected ConcreteComponent com;
public Decorate(Component component){
//可以给com初始化
super();
this.com = (ConcreteComponent) component;
}
public void method(){
com.method();
}
}
//具体装饰类 BufferInputStream InputStreamReader
class ConcreteDecorateA extends Decorate{
public ConcreteDecorateA(Component component) {
super(component);
}
public void methodA(){
System.out.println("装饰类A拓展的功能");
}
public void method(){
System.out.println("拓展原先功能");
}
}
//具体装饰类
class ConcreteDecorateB extends Decorate{
public ConcreteDecorateB(Component component) {
super(component);
}
public void methodB(){
System.out.println("装饰类B拓展的功能");
}
public void method(){
System.out.println("拓展原先功能");
}
}
3、举例理解
类比于MOBA类游戏,装饰模式为已有类动态附加额外的功能就像王者荣耀游戏中,英雄升级一样。每次英雄升级都会附加一个额外技能点学习技能。英雄的定义就是Component
,具体的英雄就是ConcreteComponent
,技能栏就是装饰器Decorator
,每个技能就是ConcreteDecorator
。
//Component 英雄接口
public interface Hero {
//学习技能
void learnSkills();
}
//ConcreteComponent 具体英雄 Luna
public class Luna implements Hero {
private String name;
public Luna(String name) {
this.name = name;
}
@Override
public void learnSkills() {
System.out.println(name + "学习了以上技能!");
}
}
//Decorator 技能栏
public abstract class Skills implements Hero{
//持有一个英雄对象接口
private Hero hero;
public Skills(Hero hero) {
this.hero = hero;
}
@Override
public void learnSkills() {
if(hero != null)
hero.learnSkills();
}
}
//ConreteDecorator 1技能
public class Skill_1 extends Skills{
private String skillName;
public Skill_1(Hero hero,String skillName) {
super(hero);
this.skillName = skillName;
}
@Override
public void learnSkills() {
System.out.println("学习了1技能:" +skillName);
super.learnSkills();
}
}
//ConreteDecorator 2技能
public class Skill_2 extends Skills{
private String skillName;
public Skill_2(Hero hero,String skillName) {
super(hero);
this.skillName = skillName;
}
@Override
public void learnSkills() {
System.out.println("学习了2技能:" + skillName);
super.learnSkills();
}
}
//ConreteDecorator 3技能
public class Skill_3 extends Skills{
private String skillName;
public Skill_3(Hero hero,String skillName) {
super(hero);
this.skillName = skillName;
}
@Override
public void learnSkills() {
System.out.println("学习了3技能:"+skillName);
super.learnSkills();
}
}
//月下无限连
public class Lunar {
public static void main(String[] args) {
//选择英雄
Hero hero = new Luna("露娜");
Skills skills = new Skills(hero);
Skills 1 = new Skill_1(skills,"弦月斩");
Skills 2 = new Skill_2(2,"炙热剑芒");
Skills 3 = new Skill_3(3,"新月突击");
//学习技能
3.learnSkills();
}
}