Java设计模式之装饰模式

来源:互联网 发布:little darling mac 编辑:程序博客网 时间:2024/05/16 04:44

Java设计模式之装饰模式

要学习并理解Java I/O,那么首先要学习Java设计模式中的装饰设计模式。

顾名思义,装饰设计模式的核心概念为通过"装饰"来扩展原有类的功能,而不是通过继承。

其要解决的主要问题是:

在某些特定情况下,需要对原有类的功能进行扩展,扩展方式有很多类型,并且相互之间存在很多组合

如果采用继承的方式来实现这个需求,那么将会产生大量的子类,整个类设计的体系结构将显得十分臃肿。

装饰的思想是:在原有类的基础上,通过将原有类对象通过构造函数传入装饰类中,装饰类在原有类功能的基础上进行增强,提供增强功能。

需要注意的是:装饰类和被装饰类应该实现同样的接口(或至少继承自同一父类),装饰类中构造函数参数的类型应写成接口形式,以便利用多态的思想,

由接口调用方法时,执行的是具体实现子类的覆盖方法。从而形成一种连锁的、链式的装饰。


下面用一个具体的例子来说明:

/** * 具体被装饰者要实现的接口 * 装饰类要与被装饰类实现同样的接口 * @author Administrator * */public interface Hamberger {public String getName();public float getPrice();}

/** * 具体的被装饰类 * 即被装饰主体是 ¥15.00 的 鸡腿堡 * @author Administrator * */public class ChickenHamberger implements Hamberger {@Overridepublic String getName() {return "鸡腿堡";}@Overridepublic float getPrice() {return 15.0f;}}

/** * 定义一个装饰类 * @author Administrator * */public abstract class Decorator implements Hamberger {private Hamberger hamberger;public Decorator(Hamberger hamberger){this.hamberger = hamberger;}@Overridepublic String getName() {return hamberger.getName();}@Overridepublic float getPrice() {return hamberger.getPrice();}}

/** * 定义一种具体的装饰 * 鸡腿堡+生菜+¥5.0 * @author Administrator * */public class DecoratorA extends Decorator {public DecoratorA(Hamberger hamberger) {super(hamberger);}public String addLettuce(){return "加生菜";}public float addPrice(){return 5f;}@Overridepublic String getName() {return super.getName()+addLettuce();}@Overridepublic float getPrice() {return super.getPrice()+addPrice();}}
/** * 定义一种具体的装饰 * 鸡腿堡+生菜+¥2.0 * @author Administrator * */public class DecoratorB extends Decorator {public DecoratorB(Hamberger hamberger) {super(hamberger);}public String addPepper(){return "加辣椒";}public float addPrice(){return 2f;}@Overridepublic String getName() {return super.getName()+addPepper();}@Overridepublic float getPrice() {return super.getPrice()+addPrice();}}
/** * 进行测试 * @author Administrator * */public class DecoratorTest {@Testpublic void test(){Hamberger hamberger = new ChickenHamberger();Decorator decorator = new DecoratorB(new DecoratorA(hamberger));String name = decorator.getName();float price = decorator.getPrice();System.out.println(name);System.out.println(price);}}
结果是:

鸡腿堡加生菜加辣椒
22.0

可以看到,通过

Decorator decorator = new DecoratorB(new DecoratorA(hamberger));
这种方式,成功地对原来的”汉堡“,增加了”生菜“和”辣椒“,如果只需要加”生菜“或者”辣椒“中的一种、或者调整其顺序的话,也只需要在这行代码中更改要用的装饰类型,并根据需要调整顺序即可。

有必要对结果的产生过程做一个分析,以

String name = decorator.getName();
为例。

通过装饰抽象类Decorator来调用getName()方法,decorator引用类型变量指向的是DecoratorB装饰类对象,将调用DecoratorB中的getName()方法。

public String getName() {return super.getName()+addPepper();}
要调用此方法,首先要调用其父类Decorator的getName()方法,

@Overridepublic String getName() {return hamberger.getName();}
这里的hamberger对象指向的是DecoratorB类型对象初始化时向其构造函数传入的DecoratorA的实例,即将执行DecoratorA的实例对象的getName()方法,

@Overridepublic String getName() {return super.getName()+addLettuce();}
同样的,也将执行DecoratorA对象父类的getName()方法,DecoratorA类型对象初始化直接依赖的是ChickenHamberger对象,

通过构造函数向其父类传入的是ChickenHamberger对象,即此时父类的hamberger引用指向的是ChickenHamberger对象。

调用其getName()方法将打印”鸡肉堡“,然后执行addLettuce()方法,”加生菜“,最后执行addPepper()方法,加”辣椒“。


价格的过程也以此类推。


总结几点:

1、可以看到,采用装饰设计模式,在避免大量子类继承的同时,增加了灵活性与动态性。即,采用子类继承,必须预先想好要扩展的功能并写死!但是采用装饰设计模式

则大可不必,根据需要,选取合适的装饰进行组合即可。

2、同时,装饰设计模式可扩展性也很好,只需要继承抽象装饰基类,定义新的装饰类型即可。





























1 0
原创粉丝点击