装饰者模式(Decorator pattern)

类型:结构型模式
要点:装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。

介绍

意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决: 一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用: 在不想增加很多子类的情况下扩展类。
如何解决: 将具体功能职责划分,同时继承装饰者模式。
关键代码:

  1. Component 类充当抽象角色,不应该具体实现。
  2. 修饰类引用和继承 Component 类,具体扩展类重写父类方法。

应用实例:

  1. 孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。
  2. 不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

优点: 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点: 多层装饰比较复杂。

使用场景:

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销。

注意事项: 可代替继承。

代码

案例一:Human

  • 被装饰者基类
/**
 * 被装饰者基类
 * @author luis
 */
public interface Human {

	/**
	 * 回家
	 */
    void goHome();

	/**
	 * 上班
	 */
	void goWork();
}
  • 具体被装饰者
/**
 * 定义被装饰者,被装饰者初始状态有些自己的装饰
 *
 * @author luis
 */
public class Person implements Human {

    @Override
    public void goHome() {
        System.out.println("回家回家,干点什么好呢");
    }

    @Override
    public void goWork() {
        System.out.println("上班上班,干点什么好呢");
    }
}

  • 装饰者基类
/**
 * 定义装饰者:实现最基本功能
 * @author luis
 */
public abstract class MyDecorator implements Human {
    private Human human;

    public MyDecorator(Human human) {
        this.human = human;
    }

    @Override
    public void goHome() {
        human.goHome();
    }

    @Override
	public void goWork() {
        human.goWork();
    }
}
  • 装饰者(对普通装饰者功能进行扩展)
/**
 * 装饰者的功能越来越多
 * @author luis
 */
public class MyDecoratorProOne extends MyDecorator {

    public MyDecoratorProOne(Human human) {
        super(human);
    }

    public void playGame() {
        System.out.println("玩联盟!");
    }

    public void problem() {
        System.out.println("项目出问题啦!");
    }

    @Override
    public void goHome() {
        super.goHome();
        playGame();
    }

    @Override
    public void goWork() {
        super.goWork();
        problem();
    }
}
  • 装饰者(对普通装饰者功能进行扩展)
/**
 * 装饰者的功能越来越多
 * @author luis
 */
public class MyDecoratorProTwo extends MyDecorator {

    public MyDecoratorProTwo(Human human) {
        super(human);
    }

    public void login() {
        System.out.println("上号!");
    }

    public void fixBug() {
        System.out.println("改bug!");
    }

    @Override
    public void goHome() {
        super.goHome();
        login();
    }

    @Override
    public void goWork() {
        super.goWork();
        fixBug();
    }
}
  • 测试
/**
 * 测试类,看一下你就会发现,跟java的I/O操作有多么相似
 */
public class Test {
	public static void main(String[] args) {
		Human person = new Person();
		MyDecorator decorator = new MyDecoratorProTwo(new MyDecoratorProOne(person));
		// 方法执行过程: two->decorator->person
		decorator.goHome();
		decorator.goWork();
	}
}
  • 结果
回家回家,干点什么好呢
玩联盟!
上号!
上班上班,干点什么好呢
项目出问题啦!
改bug!

案例二:鸡腿堡

  • 被修饰者基类
/**
 * 汉堡基类(被装饰者,相当于上面的Human)
 *
 * @author luis
 */
public abstract class Humburger {

    /**
     * 名称
     */
    protected String name;

    public String getName() {
        return name;
    }

    /**
     * 获取价格
     *
     * @return
     */
    public abstract double getPrice();


}
  • 具体被修饰者
/**
 * 鸡腿堡类(被装饰者的初始状态,有些自己的简单装饰,相当于上面的Person)
 * @author luis
 */
public class ChickenHunburger extends Humburger {

    public ChickenHunburger() {
        this.name = "鸡腿堡";
    }

    /**
     * 获取价格
     *
     * @return
     */
    @Override
    public double getPrice() {
        return 7;
    }
}
  • 装饰者基类(实现基本功能)
/**
 * 配料的基类:装饰器
 * (装饰者,用来对汉堡进行多层装饰,每层装饰增加一些配料,相当于上面Decorator)
 */
public abstract class PeiLiao extends Humburger {

    /**
     * 获取名称
     *
     * @return
     */
    @Override
    public abstract String getName();

}
  • 装饰者具体实现类(第一层)
/**
 * 生菜:(装饰者的第一层,相当于上面的decorator_one)
 *
 * @author luis
 */
public class Shengcai extends PeiLiao {

    private Humburger humburger;

    public Shengcai(Humburger humburger) {
        this.humburger = humburger;
    }

    /**
     * 获取价格
     *
     * @return
     */
    @Override
    public double getPrice() {
        return humburger.getPrice() + 2;
    }

    /**
     * 获取名称
     *
     * @return
     */
    @Override
    public String getName() {
        return humburger.getName() + " 加生菜";
    }
}

  • 装饰者具体实现类(第二层)
/**
 * 辣椒:(装饰者的第二层,相当于上面的decorator_two)
 * @author luis
 */
public class LaJiao extends PeiLiao {

    private Humburger humburger;

    public LaJiao(Humburger humburger) {
        this.humburger = humburger;
    }

    /**
     * 获取价格
     *
     * @return
     */
    @Override
    public double getPrice() {
        return humburger.getPrice()+1.5;
    }

    /**
     * 获取名称
     *
     * @return
     */
    @Override
    public String getName() {
        return humburger.getName()+" 加辣椒";
    }
}
  • 测试
	public static void main(String[] args) {
        Humburger humburger = new ChickenHunburger();
        PeiLiao shengcai = new Shengcai(humburger);
        PeiLiao laJiao = new LaJiao(humburger);
        PeiLiao ljsc = new LaJiao(shengcai);
        PeiLiao sclj = new Shengcai(laJiao);

        System.out.println(humburger.getName() + "  价钱:" + humburger.getPrice());
        System.out.println(shengcai.getName() + "  价钱:" + shengcai.getPrice());
        System.out.println(laJiao.getName() + "  价钱:" + laJiao.getPrice());
        System.out.println(ljsc.getName() + "  价钱:" + ljsc.getPrice());
        System.out.println(sclj.getName() + "  价钱:" + sclj.getPrice());
    }
  • 结果
鸡腿堡  价钱:7.0
鸡腿堡 加生菜  价钱:9.0
鸡腿堡 加辣椒  价钱:8.5
鸡腿堡 加生菜 加辣椒  价钱:10.5
鸡腿堡 加辣椒 加生菜  价钱:10.5

参考&转载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值