日常开发中,内容及其标志的OO化是经常需要我们处理的问题,下面这些都是这个问题的实际泛化:
1.文章与标签.
2.媒体文件和标签.
3.选手和各项得分.

它们的共同点是:主体内容拥有树状的标志集合.也就是说,一个内容对应一个标志集合,集合中的元素是树状的.
类图如下:

"内容"类拥有一个"标志集合"的成员,"标志集合"类拥有多个"标志"类的成员,标志类用一个parentTag成员来实现树状结构.以上三个实际例子都可以用这个模型来实现.

以"文章和标签举例",代码是:

文章类代码:
package com.sitinspring.articletags.domain;

import com.sitinspring.articletags.util.IdUtil;

public class Article extends BaseObject{
    
private String title;
    
private String concept;
    
private TagBunch tagBunch;
    
    
public Article(){
        
this("","");
    }

    
    
public Article(String title,String concept){
        
this.title=title;
        
this.concept=concept;
        
this.id=IdUtil.generateId();    
        tagBunch
=new TagBunch();
    }

    
    
public String toString(){
        String retval
="Article:"+this.id+":\n";
        
        retval
+="title="+title+"\n";
        retval
+="concept="+concept+"\n";
        retval
+="tags="+tagBunch+"\n";
        
        
return retval;
    }

    
    
public String getConcept() {
        
return concept;
    }

    
public void setConcept(String concept) {
        
this.concept = concept;
    }

    
public TagBunch getTagBunch() {
        
return tagBunch;
    }

    
public void setTagBunch(TagBunch tagBunch) {
        
this.tagBunch = tagBunch;
    }

    
public String getTitle() {
        
return title;
    }

    
public void setTitle(String title) {
        
this.title = title;
    }

}


标签类代码:
package com.sitinspring.articletags.domain;

import com.sitinspring.articletags.util.IdUtil;

public class Tag extends BaseObject{
    
// 父Tag
    private Tag parentTag;
    
    
// Tag名
    private String name;
    
    
// 构造函数,用于创建根节点
    public Tag(String name){
        
this.id=IdUtil.generateId();
        
this.name=name;
        
this.parentTag=null;
    }

    
    
// 构造函数,用于创建子节点
    public Tag(Tag parentTag,String name){
        
this.id=IdUtil.generateId();
        
this.name=name;
        
this.parentTag=parentTag;
    }

    
    
// 判断是否根节点
    public boolean isRoot(){
        
return this.parentTag==null;
    }

    
    
public String toString(){
        String retval
=name;
        
        Tag tag
=this;
        
while(!tag.isRoot()){
            tag
=tag.getParentTag();
            retval
=tag.getName()+"."+retval;
        }

        
        
return "Tag:"+this.id+":\n"+retval;
    }


    
public String getName() {
        
return name;
    }

    
    
public void setName(String name) {
        
this.name = name;
    }


    
public Tag getParentTag() {
        
return parentTag;
    }

}


标签集合类代码:
package com.sitinspring.articletags.domain;

import java.util.Hashtable;
import java.util.Iterator;

import com.sitinspring.articletags.util.IdUtil;

public class TagBunch extends BaseObject{
    
private Hashtable<String,Tag> tags;    
    
    
public TagBunch(){
        
this.id=IdUtil.generateId();
        tags
=new Hashtable<String,Tag>();
    }

    
    
public boolean addTag(Tag tag){
        
if(tags.containsKey(tag.getId())){
            
return false;
        }

        
else{
            tags.put(tag.getId(), tag);
            
return true;
        }

    }

    
    
public boolean removeTag(Tag tag){
        
if(!tags.containsKey(tag.getId())){
            
return false;
        }

        
else{
            tags.remove(tag.getId());
            
return true;
        }

    }

    
    
public String toString(){
        String retval
="";
        
        
for (Iterator it=tags.keySet().iterator(); it.hasNext(); ) {
            String key 
=(String) it.next();
            Tag tag 
= tags.get(key);
            retval
+=tag+",";
        }

        
        
return "TagBunch:"+this.id+":\n"+retval;
    }

}


存入DB4O数据库过程:
         // 创建过程
        Tag javaTag=new Tag("java");
        Tag j2eeTag
=new Tag(javaTag,"j2ee");
        Tag jspTag
=new Tag(j2eeTag,"jsp");
        Tag ejbTag
=new Tag(j2eeTag,"ejb");
        
        Article jspArticle
=new Article("jsp","jsp中自定义标签的制作");
        jspArticle.getTagBunch().addTag(jspTag);
        System.out.println(jspArticle);
        
        Article j2eeArticle
=new Article("Java WebApp的分层设计","前台:jsp 后台:Ejb");
        j2eeArticle.getTagBunch().addTag(jspTag);
        j2eeArticle.getTagBunch().addTag(ejbTag);        
        System.out.println(j2eeArticle);
        
        Article javaArticle
=new Article("Java的演化","从1995到2007");
        javaArticle.getTagBunch().addTag(javaTag);
        System.out.println(javaArticle);
        
        
// 存储过程
        Service<BaseObject> service=new Service<BaseObject>();
        service.add(jspArticle);
        service.add(j2eeArticle);
        service.add(javaArticle);


从DB4O数据库取出过程:
        // 取出过程
        
// (1) 取所有
        Service<BaseObject> objService=new Service<BaseObject>();
        List
<BaseObject> objs=objService.getAll();
        
        
for(BaseObject obj:objs){
            System.out.println(obj);
        }

        
        
// (2) 取所有Article
        Service<Article> articleService=new Service<Article>();
        List
<Article> articles=articleService.getAll(Article.class.getName());        
        
for(Article article:articles){
            System.out.println(article);                        
        }


Service类实现
package com.sitinspring.articletags.service;

import java.util.List;

import com.db4o.query.Predicate;
import com.sitinspring.articletags.dao.Db4ODao;
import com.sitinspring.articletags.domain.BaseObject;

public class Service<extends BaseObject> {
    
private Db4ODao<K> dao;
    
    
public Service() {
        dao
=new Db4ODao<K>();
    }


    
public boolean add(K obj) {
        
if(hasId(obj.getId())){
            
return false;
        }
else{
            dao.add(obj);
            
return true;
        }
    
    }


    
public boolean update(K obj) {
        
return true;
    }


    
public boolean saveOrUpdate(K obj) {
        
if (hasId(obj.getId())) {
            
return update(obj);
        }
 else