Decorator模式有代理的味道

thy3368發表於2004-02-03
這是一個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.其中一個實現類引用了另一個實現類,並作了功能的增加




相關文章