java设计模式之装饰者模式

    xiaoxiao2021-03-26  13

    一、定义


    装饰(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变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.

    转载请注明原文地址: https://ju.6miu.com/read-450266.html

    最新回复(0)