posts - 262,  comments - 221,  trackbacks - 0

前面我们看了Decorator模式的一下理论基础,知道了Decorator模式的适应场合是:在运行时刻由用户动态决定加入的方式和时机,无法在编译期间决定。下面我们就以一个实际的例子来了解一下Decorator模式的实际应用。

一、应用场景:

假设我们已经存在这样的一个程序:

1).该程序从一个列表中拿出所有的用户名单,然后逐个向用户发送一句信息。
2).现在我们又增加了一个新的需求:在发送之前检查一下该用户是否存在于黑名单中,如果是的话则不发送给该用户。
3).是否进行检查则动态根据用户的当时需要来决定。

二、需求分析:

从上面的情况分析,如果我们采用继承的方式,重新编写一个带有过滤功能的发送程序,则必须完全改写原有的发送方法,插入过滤的过程。如果我们采用Decorator模式的话,可以怎么做呢?

首先分析一下需求的公共部分,相同的部分都是发送信息,不管是否需要进行过滤。也就是说只有发送的方法拿到数据,它就不管三七二十一发出去了,所以这个功能应该可以被抽象成一个接口。

接下来我们来看一下,既然新的功能只是在旧的功能之前插入了“过滤”这一简单的过程,原有的功能保持不变,所以我们完全可以把旧的功能委托给老的程序来进行。既然是委托了那么必然在新的类里面要含有一个旧的对象的引用。

最后如何实现“动态插入过滤功能”呢?我们看一下前面的接口,如果我们实现了接口,那么在其实现方法中就可以重写原来的方法,增加过滤功能了。

三、系统设计:

我们来看一下下面这张图,明确一下各个对象之间的联系





在这张图中我们看到:我们抽象出了一个接口:ISendMessage接口,原有的SendMessageImpl类和新增的SendMessageDecorator类都实现了该接口。Decorator类有一个对SendMessageImpl的委托。

四、详细代码:

·ISendMessage:

package org.pattern.decorator;

public interface ISendMessage {

    
public void send();
}


·SendMessageImpl:

package org.pattern.decorator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SendMessageImpl implements ISendMessage {

    List
<String> users = new ArrayList<String>();
    
    
public void setUsers(List<String> users) {
        
this.users = users;
    }


    
public List<String> getUsers() {
        
return users;
    }


    
// Implement
    public void send() {
        
for (Iterator it = users.iterator(); it.hasNext();) {
            String user 
= (String) it.next();
            System.out.println(
"This is for your message : " + user);
        }

    }


}


·SendMessageDecorator:

package org.pattern.decorator;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class SendMessageDecorator implements ISendMessage {

    
private ISendMessage isendMessage;

    
private boolean filter = false;

    
private List<String> blackUsers = new ArrayList<String>();
    
    
// Constructor method
    public SendMessageDecorator(ISendMessage isendMessage){
        
this.isendMessage = isendMessage;
    }


    
// Constructor method with filter flag and black user list
    public SendMessageDecorator(ISendMessage isendMessage, boolean filter,
            List
<String> blackUsers) {
        this.isendMessage = isendMessage;
        this.filter = filter;
        
this.blackUsers = blackUsers;
    }


    
// Decorator operation: dynamicly add filter logic if needed
    public void send() {
        
if (!filter) {
            isendMessage.send();
        }
 else {
            filter(blackUsers);
            isendMessage.send();
        }

    }


    
private void filter(List<String> blackUsers) {
        
// Return if black users list is null
        if (blackUsers == null{
            
return;
        }

        
// Remove all users which mattch the black list
        List users = ((SendMessageImpl) isendMessage).getUsers();
        List
<String> newList = new ArrayList<String>();
        
for (Iterator it = users.iterator(); it.hasNext();) {
            String user 
= (String) it.next();
            
if (!blackUsers.contains(user)) {
                newList.add(user);    
            }

        }

        ((SendMessageImpl)isendMessage).setUsers(newList);
    }


}


·DecoratorTest:

package org.pattern.decorator;

import java.util.ArrayList;
import java.util.List;

public class DecoratorTest {

    
public static void main(String args[]) {
        DecoratorTest dt 
= new DecoratorTest();
        dt.test(args[
0]);    
    }


    
private void test(String arg) {
        
// Create users
        List<String> users = new ArrayList<String>();
        users.add(
"Paul");
        users.add(
"Bob");
        users.add(
"Tom");
        users.add(
"Jim");
        
// Set users
        SendMessageImpl sender = new SendMessageImpl();
        sender.setUsers(users);
        
// Create Decorator
        if (arg == null || arg.trim().length() == 0 || arg.equalsIgnoreCase("no")) {
            ISendMessage decorator 
= new SendMessageDecorator(sender);
            decorator.send();
        }
 else {
            List
<String> blackUsers = new ArrayList<String>();
            blackUsers.add(
"Tom");
            blackUsers.add(
"Jim");
           ISendMessage decorator = new SendMessageDecorator(sender, true,
                    blackUsers);
            decorator.send();

        }

    }


}


五、Decorator模式的特点:

A. Decorator类实现了接口(抽象)
B. Decorator类中包含一个接口类型的属性,并通过适当的方式被实例化
C. Decorator类中实现接口的抽象方法,委托父类属性完成基本功能,同时加入额外功能或改变工作流



-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2008-02-19 18:31 Paul Lin 阅读(1761) 评论(0)  编辑  收藏 所属分类: 模式与重构

只有注册用户登录后才能发表评论。


网站导航:
 
<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜