Java设计模式--修饰模式

什么是修饰模式

修饰模式是面向对象模式的一种,该模式可以动态向类中添加新的功能。动态指的是在程序运行时候,而我们常用的扩展功能的方法是写一个子类继承父类,这样的继承是静态的,因为这样的扩展方法是程序编译时候就体现出来了。

Decorator Pattern Implementation - UML Class Diagram


在上图中可以看到,接口类Component有2个实现,ConcreteComponent类和Decorator类,Decorator类和它的2个子类对ConcreatedComponent类做了修饰, 这样的实现方式就是修饰模式。子类ConcreteDectoratorExtendingFunctionality和ConcreteDecoratorExtendingState类在ConcreatedComponent类的基础之上增加了新的功能。


修饰模式存在的作用


之前讨论定义时候说到动态的增加类的功能是修饰模式的作用,而子类增加功能的方式是静态的。子类这样的增加方式并不完美。假设这样的情况,需要给一个类PClass增加特性A,于是我们有了子类APClass, 需要特性B,于是有了BPClass, 需要特性C,有了CPClass, 现在需要特性AB,可以定义子类ABPClass,这已经有了很多的子类了,如果我们还需要把这些特性任意的组合的话,这个子类就更加的复杂了。并且,我们在编译这个子类的时候,实例化了ABPClass, BPClass , PClass这三个类。于是, 功能就像是类的模板的一样,不同的功能不同的模板,极度不方便。

修饰模式解决的就是这样的问题,修饰类在PClass的基础可以直接添加特性A和B, 没有子类BPClass需要被实例化。并且调用PClass的实例也是在代码的运行时,这个就是动态的了。


请看下面的代码。代码源自wikipedia.

    //接口,我们想要扩展的就是window类的功能  
    public interface Window {  
        public void draw();  
        public String getDescription();  
    }  

    //实现类  
    public class SimpleWindow implements Window {  
      
        @Override  
        public void draw() {  
            System.out.println("draw window");  
        }  
      
        @Override  
        public String getDescription() {  
            return "Simple Window";  
        }  
      
    }  

    //window的修饰类,这里使用的修饰方法为将window做参数传入构造方法中,这样的话,修饰类的子类可以动态的增加新的功能,也就是不需要编译时候就实例化window类了。  
    public abstract class WindowDecorator implements Window {  
        protected Window decoratedWindow;  
          
        public WindowDecorator(Window decoratedWindow){  
            this.decoratedWindow = decoratedWindow;  
        }  
    }  

修饰者类 VScrollBarDecorator

    //修饰类的一个子类。为window类增加了新的方法 drawVScrollBar.  
    public class VScrollBarDecorator extends WindowDecorator {  
      
        public VScrollBarDecorator(Window decoratedWindow) {  
            super(decoratedWindow);  
        }  
      
        //这里可以看到window的功能方便的被扩展了,调用decoratedWindow.draw之前还可以增加其他的功能。并且在使用该方法的时候,才会去实例化window和decoratedWindow  
        @Override  
        public void draw() {  
            drawVScrollBar();  
            decoratedWindow.draw();  
        }  
      
        private void drawVScrollBar(){  
              
        }  
          
        @Override  
        public String getDescription() {  
            return decoratedWindow.getDescription() + "-- include vscorllbar";  
        }  
      
    }  

修饰者类

HScrollBarDecorator 

/另外一个增加了功能那个的类  
public class HScrollBarDecorator extends WindowDecorator{  
  
    public HScrollBarDecorator(Window decoratedWindow) {  
        super(decoratedWindow);  
    }  
  
    @Override  
    public void draw() {  
        drawHScrollBar();  
        decoratedWindow.draw();  
    }  
  
    private void drawHScrollBar(){  
    }  
  
    @Override  
    public String getDescription() {  
        return decoratedWindow.getDescription() + "--include hscrollbar";  
    }  
  
}  

最近看一下测试:

public class DecoratedWindowTest {  
      
    public static void main(String[] args){  
        //这里可以看到原来见到的SimpleWindow就有了HScrollbar和VScrollBar  
        Window decoratedWindow = new HScrollBarDecorator(  
                new VScrollBarDecorator(new SimpleWindow()));  
        System.out.println(decoratedWindow.getDescription());  
    }  
      
}

上面的代码中,给SimpleWindow增加2个特性HScrollBar和VScrollBar。若是在用子类的情况下,那么就需要定义至少三个子类。但是在使用修饰模式的情况下, 新的特性只需要在实例化时当作参数传进去就可以了。


多看,多练,多用,才能更加深刻的理解。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值