初识设计模式之装饰者模式
一、为什么要用装饰者模式
我们来看一个例子,比如现在有一家餐巾纸工厂,用来生产抽纸和卷纸。如下代码所示:
interface TissueFactory{
public void produce();
}
class Rolltissu implements TissueFactory{
public void produce() {
System.out.println("生产卷纸");
}
}
class Removabletissu implements TissueFactory{
public void produce() {
System.out.println("生产抽纸");
}
}
运营了一段时间后,工厂决定对抽纸和卷纸的生产策略进行升级,对二者都进行3层纸和4层纸的生产。一般情况下,我们想到用继承去实现:
interface TissueFactory{
public void produce();
}
class Rolltissu implements TissueFactory{
public void produce() {
System.out.println("生产卷纸");
}
}
class Removabletissu implements TissueFactory{
public void produce() {
System.out.println("生产抽纸");
}
}
class ThreeRolltissu extends Rolltissu{
@Override
public void produce() {
System.out.println("生产三层的卷纸");
}
}
class FourRolltissu extends Rolltissu{
@Override
public void produce() {
System.out.println("生产四层的卷纸");
}
}
class ThreeRemovabletissu extends Removabletissu{
@Override
public void produce() {
System.out.println("生产三层的抽纸");
}
}
class FourRemovabletissu extends Removabletissu{
@Override
public void produce() {
System.out.println("生产四层的抽纸");
}
}
这样一来,需求不就决解了吗?再后来,工厂又进行升级,要生产2层纸和5层纸厚的卷纸和抽纸,这样一来,类的数量增加地非常快。于是,装饰者模式登场了。
二、怎么用装饰者模式
接着上面的第二段,即回到工厂刚进行生产策略升级的部分。此时工厂的卷纸和抽纸都分别要生产三层、四层纸厚的纸,此时我们用装饰者模式进行设计:
interface TissueFactory{
public void produce();
}
class Rolltissu implements TissueFactory{
public void produce() {
System.out.println("生产卷纸");
}
}
class Removabletissu implements TissueFactory{
public void produce() {
System.out.println("生产抽纸");
}
}
//装饰的是TissueFactory
abstract class TissueDecorator implements TissueFactory{
protected TissueFactory tissueFactory;
public TissueDecorator(TissueFactory tissueFactory){
this.tissueFactory = tissueFactory;
}
}
class ThreeTissue extends TissueDecorator{
public ThreeTissue(TissueFactory tissueFactory) {
super(tissueFactory);
}
public void produce() {
System.out.print("使用三层纸工艺:");
tissueFactory.produce();
}
}
class FourTissue extends TissueDecorator{
public FourTissue(TissueFactory tissueFactory) {
super(tissueFactory);
}
public void produce() {
System.out.print("使用四层纸工艺:");
tissueFactory.produce();
}
}
public class Run {
public static void main(String[] args) {
System.out.println("在生产策略不变时:");
TissueFactory rollTf = new Rolltissu();
TissueFactory removableTf = new Removabletissu();
rollTf.produce();
removableTf.produce();
System.out.println("在生产策略改变时:");
//对原来的工艺流程进行装饰,需要一个被装饰的对象
TissueFactory threeRoll = new ThreeTissue(rollTf);
TissueFactory FourRoll = new FourTissue(rollTf);
TissueFactory threeRemovable = new ThreeTissue(removableTf);
TissueFactory FourRemovable = new FourTissue(removableTf);
threeRoll.produce();
FourRoll.produce();
threeRemovable.produce();
FourRemovable.produce();
}
}
如此一来,当我们又进行产业升级时,如新增2层和5层工艺时,我们只需要加上2层和5层的装饰者就行了。
三、装饰者模式再理解
优点:
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能。
- 通过使用不同装饰类以及这些类的排列组合,可以实现不同的效果。
- 符合开闭原则
缺点:
- 会出现更多的代码,更多的类,增加程序的复杂性。
- 动态装饰时,多层装饰时会更复杂。
- 装饰模式会产生比使用继承关系更多的对象。