java设计模式之装饰者模式

一、定义


装饰(decorate)模式又称为包装(Wrapper)模式,顾名思义,装饰模式就是对XXX进行包装,使其功能,职责更加完善;说白了就是给对象增加新的功能,是继承关系的一个替代方案。

二、为什么要使用Decorator模式?


我们通常来使用继承来实现功能的扩展,如果这些需要扩展的功能很繁多,那么势必会增加系统的复杂性,使程序显得十分的“臃肿”,耦合度很高,同时,使用继承实现功能的扩展,我们必须可预见这些扩展功能,这些功能是编译时就确定的,是静态的。

思想:为一个对象已有的子类添加一些额外的职责。

三、继承方式实现功能的扩展


1、简单案例

代码实例:

抽象接口

public interface AbstractCar {
    public abstract void move();
}

基础实现

public class CarImpl implements AbstractCar{

    @Override
    public void move() {
        System.out.println("car is driving on the highway");
    }
}

功能扩展(飞行)

public class FlyCar extends CarImpl {

    public void fly(){
        System.out.println("car is driving in the air");
    }

    @Override
    public void move() {
        super.move();
        fly();
    }

}

功能扩展(水行)

public class FlyAndSwimCar extends FlyCar {

    public void swim(){
        System.out.println("car is driving in the water");
    }

    @Override
    public void move() {
        super.move();
        swim();
    }

}

测试类

public class Tester {

    public static void main(String[] args) {
        AbstractCar car1 = new CarImpl();
        car1.move();
        System.out.println("------add fly function-----");
        AbstractCar car2 = new FlyCar();
        car2.move();
        System.out.println("------add swiming function-----");
        AbstractCar car3 = new FlyAndSwimCar();
        car3.move();
    }

}

输出

car is driving on the highway
------add fly function-----
car is driving on the highway
car is driving in the air
------add swiming function-----
car is driving on the highway
car is driving in the air
car is driving in the water

四、分析



首先我们先来看下类的继承体系

Car
    |--FlyCar
        |--FlyAndSwim
            |--新增其他功能
    |--SwimCar
    |--CarImpl

如果我们有更多的需求,这个继承体系会愈来愈大;这时,我们就可以使用装饰者模式。

五、装饰(Decorate)模式


1、简单案例1

代码实例

被装饰者

/**
 * 抽象汽车类,被装饰者
 * @author Administrator
 *
 */
public interface Car {
    public abstract void move();
}

装饰者

public abstract class CarDecorator implements Car {

    private Car car;

    public CarDecorator(Car car) {
        this.car = car;
    }

    @Override
    public void move() {
        this.car.move();
    }
}

被装饰者初始装饰

public class CarImpl implements Car {
    /**
     * 被装饰者初始状态有些自己的装饰
     */
    @Override
    public void move() {
        System.out.println("car is moving on the highway");
    }

}

水行装饰

public class SwimingCar extends CarDecorator {

    public SwimingCar(Car car) {
        super(car);
    }

    public void DrivingInWater(){
        System.out.println("car is driving in the water");
    }

    @Override
    public void move() {
        super.move();
        DrivingInWater();
    }
}

飞行装饰

public class FlyCar extends CarDecorator {

    public FlyCar(Car car) {
        super(car);
    }

    public void DrivingInAir(){
        System.out.println("car is driving in the air");
    }
    @Override
    public void move() {
        super.move();
        DrivingInAir();
    }   
}

测试类

    public static void main(String[] args) {
        Car car = new CarImpl();
        car.move();

        System.out.println("---------------");
        CarDecorator fly = new FlyCar(car);
        fly.move();

        System.out.println("---------------");
        CarDecorator swiming = new SwimingCar(car);
        swiming.move();

        System.out.println("---------------");
        CarDecorator flyAndSwim = new FlyCar(swiming);
        flyAndSwim.move();
    }

}

我们再来看下他的继承体系

Car
    |--CarDecorator
        |--FlyCar
        |--SwimingCar
        |--其他装饰
            
            
            
    |--CarImpl

由此可知、使用装饰模式他的继承体系不像单纯的使用继承那样庞大。

1、简单案例2

代码实例

被装饰者

/**
 * 定义被装饰者
 * 
 * @author Administrator
 * 
 */
public abstract class Pancake {
    protected String name;

    public String getName() {
        return name;
    }

    public abstract double getPrice();
}

装饰者

/**
 * 定义装饰者
 * 
 * @author Administrator
 * 
 */
public abstract class PancakeDecorate extends Pancake {

    private Pancake pancake;

    public PancakeDecorate(Pancake pancake) {
        this.pancake = pancake;
    }

    @Override
    public String getName() {
        return this.pancake.getName();
    }

    @Override
    public double getPrice() {
        return this.pancake.getPrice();
    }

}

初始化装饰

public class PancakeInit extends Pancake {

    public PancakeInit(){
        name = "煎饼";
    }

    @Override
    public double getPrice() {
        return 8;
    }
}

生菜装饰

public class LettuceDecorate extends PancakeDecorate {

    public LettuceDecorate(Pancake pancake) {
        super(pancake);
    }

    @Override
    public String getName() {
        return super.getName()+"  加生菜";
    }

    @Override
    public double getPrice() {
        return super.getPrice()+1;
    }

}

鸡蛋装饰

public class EggDecorate extends PancakeDecorate {

    public EggDecorate(Pancake pancake) {
        super(pancake);
    }


    @Override
    public String getName() {
        return super.getName()+"加鸡蛋";
    }

    @Override
    public double getPrice() {
        return super.getPrice()+2;
    }

}

火腿装饰

public class HamDecorate extends PancakeDecorate {

    public HamDecorate(Pancake pancake) {
        super(pancake);
    }

    @Override
    public String getName() {
        return super.getName()+"  加火腿";
    }

    @Override
    public double getPrice() {
        return super.getPrice()+2;
    }

}

测试类

public class Tester {

    public static void main(String[] args) {
        // 基本的煎饼
        Pancake pancake = new PancakeInit();
        System.out.println(pancake.getName() + "  价格:" + pancake.getPrice());
        // 只加生菜
        PancakeDecorate pd = new LettuceDecorate(pancake);
        System.out.println(pd.getName() + "  价格:" + pd.getPrice());
        // 只加火腿
        pd = new HamDecorate(pancake);
        System.out.println(pd.getName() + "  价格:" + pd.getPrice());
        // 加鸡蛋,加火腿
        pd = new HamDecorate(new LettuceDecorate(pancake));
        System.out.println(pd.getName() + "  价格:" + pd.getPrice());
    }
}

输出

煎饼  价格:8.0
煎饼  加生菜  价格:9.0
煎饼  加火腿  价格:10.0
煎饼  加生菜  加火腿  价格:11.0

六、总结


个人理解:装饰者模式的设计对扩展开放、对修改关闭,体现在如果我想扩展被装饰者的职责,无须修改装饰者抽象类,只需要继承装饰者抽象类,实现额外的装饰或者职责只需要对被装饰者进行包装即可。

如果你细心的话上面示例的调用类似于我们读取文件时的调用:

FileReader fr = new FileReader("a.txt");
BufferedReader br = new BufferedReader(fr);

实际上Java 的I/O API就是使用装饰模式实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值