Decorator模式有代理的味道

04-02-03 thy3368
    

这是一个Decorator模式例子的简单的三个文件

我们先建立一个接口:

public interface Work

{

  public void insert();

}

接口Work有一个具体实现:插入方形桩或圆形桩,这两个区别对Decorator是无所谓.我们以插入方形桩为例:

public class SquarePeg implements Work{

  public void insert(){

    System.out.println("方形桩插入");

  }

}

现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需要在打桩之后钉架子(只是比喻).

那么我们使用Decorator模式,这里方形桩SquarePeg是decoratee(被刷油漆者),我们需要在decoratee上刷些"油漆",这些油漆就是那些额外的功能.

public class Decorator implements Work{

  private Work work;

  //额外增加的功能被打包在这个List中

  private ArrayList others = new ArrayList();

  //在构造器中使用组合new方式,引入Work对象;

  public Decorator(Work work)

  {

    this.work=work;

  

    others.add("挖坑");

    others.add("钉木板");

  }

  public void insert(){

    newMethod();

  }

  

  //在新方法中,我们在insert之前增加其他方法,这里次序先后是用户灵活指定的   

  public void newMethod()

  {

    otherMethod();

    work.insert();

  }

  public void otherMethod()

  {

    ListIterator listIterator = others.listIterator();

    while (listIterator.hasNext())

    {

      System.out.println(((String)(listIterator.next())) + " 正在进行");

    }

  }

}

好了,Decorator模式出来了,客户端也的代码:

Work squarePeg = new SquarePeg();

Work decorator = new Decorator(squarePeg);

decorator.insert();

在ForumPermissions中定义了各种级别权限的用户:

public class ForumPermissions implements Cacheable {

/**

* Permission to read object.

*/

public static final int READ = 0;

/**

* Permission to administer the entire sytem.

*/

public static final int SYSTEM_ADMIN = 1;

/**

* Permission to administer a particular forum.

*/

public static final int FORUM_ADMIN = 2;

/**

* Permission to administer a particular user.

*/

public static final int USER_ADMIN = 3;

/**

* Permission to administer a particular group.

*/

public static final int GROUP_ADMIN = 4;

/**

* Permission to moderate threads.

*/

public static final int MODERATE_THREADS = 5;

/**

* Permission to create a new thread.

*/

public static final int CREATE_THREAD = 6;

/**

* Permission to create a new message.

*/

public static final int CREATE_MESSAGE = 7;

/**

* Permission to moderate messages.

*/

public static final int MODERATE_MESSAGES = 8;

.....

public boolean isSystemOrForumAdmin() {

  return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);

}

.....

}

因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来.比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:

public class ForumProxy implements Forum {

private ForumPermissions permissions;

private Forum forum;

this.authorization = authorization;

public ForumProxy(Forum forum, Authorization authorization,

ForumPermissions permissions)

{

this.forum = forum;

this.authorization = authorization;

this.permissions = permissions;

}

.....

public void setName(String name) throws UnauthorizedException,

ForumAlreadyExistsException

{

  //只有是系统或论坛管理者才可以修改名称

  if (permissions.isSystemOrForumAdmin()) {

    forum.setName(name);

  }

  else {

    throw new UnauthorizedException();

  }

}

...

}

而DbForum才是接口Forum的真正实现,以修改论坛名称为例:

public class DbForum implements Forum, Cacheable {

...

public void setName(String name) throws ForumAlreadyExistsException {

  ....

  this.name = name;

  //这里真正将新名称保存到数据库中

  saveToDb();

  ....

}

...

}

凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的"网关","安全代理系统".

在平时应用中,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用Proxy,实际你已经在使用Proxy了.

我们继续结合Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:设计模式之Factory

我们已经知道,使用Forum需要通过ForumProxy,Jive中创建一个Forum是使用Factory模式,有一个总的抽象类ForumFactory,在这个抽象类中,调用ForumFactory是通过getInstance()方法实现,这里使用了Singleton(也是设计模式之一,由于介绍文章很多,我就不写了,看这里),getInstance()返回的是ForumFactoryProxy.

为什么不返回ForumFactory,而返回ForumFactory的实现ForumFactoryProxy?

原因是明显的,需要通过代理确定是否有权限创建forum.

在ForumFactoryProxy中我们看到代码如下:

public class ForumFactoryProxy extends ForumFactory {

  protected ForumFactory factory;

  protected Authorization authorization;

  protected ForumPermissions permissions;

  public ForumFactoryProxy(Authorization authorization, ForumFactory factory,

  ForumPermissions permissions)

  {

    this.factory = factory;

    this.authorization = authorization;

    this.permissions = permissions;

  }

  public Forum createForum(String name, String description)

      throws UnauthorizedException, ForumAlreadyExistsException

  {

    //只有系统管理者才可以创建forum

    if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {

      Forum newForum = factory.createForum(name, description);

      return new ForumProxy(newForum, authorization, permissions);

    }

    else {

      throw new UnauthorizedException();

  }

}

由上面可以找到两个共同点为

1.两个实现类都派生于同一个接口

2.其中一个实现类引用了另一个实现类,并作了功能的增加