设计模式-Decorator模式

Decorator模式定义:动态给一个对象添加一些额外的职责,它是通过创建一个包装对象,也就是装饰来包裹真实的对象。就像在墙上刷油漆,使用Decorator模式相比使用生成子类方式达到功能的扩充更加灵活。


为什么使用Decorator:我们通常可以使用继承来实现功能的扩展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性。同时,使用继承实现功能的拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定的,是静态的。使用Decorator的理由:Decorator提供了“即插即用”的方法,在运行期间决定何时增加何种功能。


装饰模式在Java种使用很广泛,比如我们在重新定义按钮、对话框等时候,实际上已经在使用装饰模式了。装饰模式使用被装饰类的一个子类的实例,把客户端的调用委派到被装饰类,装饰模式的关键在于这种扩展是完全透明的。

原理图

其中类的职责如下:
 
抽象构件角色(Project):给出一个接口,以规范准备接收附加责任的对象
具体构件角色(Employe):定义一个将要接收附加责任的类
装饰角色(Manager):持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口
具体装饰角色(ManagerA、ManagerB):负责给构件对象“贴上”附加的责任
 
下面通过一个软件项目例子来说明装饰模式的使用
过程是这样的:
项目经理接到一个项目,项目最终要完成编码。
项目经理接到项目后,先做些前期的工作(比如需求分析、设计),然后将编码工作委派给代码工人,代码工人干完后,项目经理做项目的收尾工作。

public interface Project {
    void doCoding();//写代码
}

public class Employe implements Project{     

    public void doCoding(){ 
        System.out.println("代码工人在痛苦的写代码"); 
    } 
}

public class Manager implements Project { 

    private Project project; 

    public Manager(Project project) { 
        this.project = project; 
    } 

    public void doCoding() { 
        startNewWork(); 
    } 
    
    public void startNewWork() { 
        doEarlyWork(); 
        project.doCoding(); 
        doEndWork(); 
    } 

    public void doEarlyWork() { 
    } 
    
    public void doEndWork() {
    } 
}


public class ManagerA extends Manager{ 


    public ManagerA(Project project) { 
        super(project); 
    } 
    
    public void doEarlyWork() {
        System.out.println("项目经理A 在做需求分析"); 
        System.out.println("项目经理A 在做架构设计"); 
        System.out.println("项目经理A 在作详细设计"); 
    } 
}

public class ManagerB extends Manager { 


    public ManagerB(Project project) { 
        super(project); 
    } 
     
    public void doEarlyWork() {
        System.out.println("项目经理B 在作需求分析"); 
        System.out.println("项目经理B 在做详细设计"); 
    } 
    
    public void doEndWork() {
        System.out.println("项目经理B 在做收尾工作"); 
    } 
}

public class Client { 
    public static void main(String args[]) { 
        Project employe = new Employe();        
        Project managerA = new ManagerA(employe); 
        Project managerB = new ManagerB(employe);
        managerA.doCoding(); 
        managerB.doCoding(); 
    } 
}



运行结果:

项目经理A 在做需求分析
项目经理A 在做架构设计
项目经理A 在做详细设计
代码工人 在编写代码,加班编啊编啊,终于编完了!
项目经理B 在做需求分析
项目经理B 在做详细设计
代码工人 在编写代码,加班编啊编啊,终于编完了!
项目经理B 在做收尾工作 

装饰模式的特点; 
(1) 装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。 
(2) 装饰对象包含一个真实对象的索引(reference) 
(3) 装饰对象接受所有的来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构          就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

装饰模式 VS 继承 
装饰模式                                               继承 
用来扩展特定对象的功能                        用来扩展一类对象的功能 
不需要子类                                           需要子类 
动态地                                                  静态地 
运行时分配职责                                     编译时分派职责 
防止由于子类而导致的复杂和混乱           导致很多子类产生,在一些场合,报漏类的层次 
更多的灵活性                                        缺乏灵活性 
对于一个给定的对象,同时可能有             
不同的装饰对象,客户端可以通过
它的需要选择合适的装饰对象发送
消息。                                                  对于所有可能的联合,客户期望 
                                                            很容易增加任何的 困难


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值