デザイン パターンを理解して使用することで、オブジェクト指向プログラミングの優れた習慣を身につけることができます。同時に、実際のアプリケーションでは、水を得た魚のように、簡単な楽しさを楽しむことができます。
プロキシはより便利なモードであり、アプリケーション シナリオは、プロキシ サーバーなどの小さな構造から大規模な構造までをカバーします。出発点と目的地の間には中間層があり、これは代理店を意味します。 デザインパターンの定義: このオブジェクトへのアクセスを制御するために、他のオブジェクトにプロキシを提供します。 プロキシ モードを使用する理由1. 認可メカニズム 異なるレベルのユーザーは、同じオブジェクトに対して異なるアクセス権を持っています。たとえば、Jive フォーラム システムでは、認可メカニズムの制御に 2 つのタイプのユーザーが使用されます。フォーラム: 登録ユーザーと訪問者 (未登録ユーザー)。Jive は ForumProxy などのプロキシを使用して、これら 2 人のユーザーのフォーラムへのアクセス権を制御します。2. クライアントはオブジェクトを直接操作することはできませんが、そのオブジェクトと対話する必要があります。
2. オブジェクトがインターネット上のリモート サーバー上にある場合、ネットワーク速度のせいでオブジェクトを直接操作すると遅くなる可能性があるため、最初にプロキシを使用してオブジェクトを置き換えることができます。
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 のさまざまな操作権限は、Forum: ForumProxy インターフェイスの実装として、まさにこの対応関係になります。 。たとえば、フォーラムの名前を変更するには、フォーラム管理者またはシステム管理者のみが変更できます。コードは次のとおりです。
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 は、フォーラム名の変更を例に挙げます。 :
public class DbForum implements Forum, Cacheable { ... public void setName(String name) throws ForumAlreadyExistsException { .... this.name = name; //这里真正将新名称保存到数据库中 saveToDb(); .... } ... }フォーラム名の変更に関わるすべて このイベントを変更するには、他のプログラムが最初に ForumProxy を処理する必要があります。ForumProxy が真の「ゲートウェイ」および「セキュリティ プロキシ システム」であるかどうかを判断します。 。 日常のアプリケーションでは、意識的にプロキシを使用するかどうかにかかわらず、システムの承認やセキュリティ システムが常に関与することは避けられず、実際にはすでにプロキシを使用しています。 Jive についてさらに詳しく説明していきます。以下ではファクトリー モードについて説明します。 Forum を使用するには ForumProxy が必要であることはすでにわかっています。Jive でフォーラムを作成するには、一般的な抽象クラス ForumFactory があり、ここでは getInstance() メソッドを使用して実装されます。これも設計パターンの 1 つです)、getInstance() は ForumFactoryProxy を返します。 ForumFactory を返さず、ForumFactory の実装である ForumFactoryProxy を返すのはなぜですか?理由は明らかです。フォーラムを作成する権限があるかどうかを確認するには、プロキシを使用する必要があります。 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(); } } }メソッド createForum も ForumProxy を返します。プロキシは壁のようなものです。他のプログラムはプロキシとのみ対話できます。 ここには、ForumProxy と ForumFactoryProxy という 2 つのプロキシがあることに注意してください。フォーラムの使用とフォーラムの作成という 2 つの異なる責任を表します。オブジェクトの使用とオブジェクトの作成が分離されている理由については、「カプセル化」と「ディスパッチ」のために Factory パターンが使用される理由でもあります。言い換えれば、保守や変更を容易にするために、機能は可能な限りシンプルである必要があります。 Jive フォーラム システム内の他の投稿の作成と使用は、すべてフォーラムの考え方に基づいています。 上では、プロキシを使用して認証メカニズムにアクセスする方法について説明しました。プロキシは、コピーオンライトと呼ばれる別の最適化方法をユーザーから隠すこともできます。大きくて複雑なオブジェクトのコピーはコストのかかる操作です。コピー プロセス中に元のオブジェクトが変更されない場合、そのようなコピーのオーバーヘッドは不要です。プロキシを使用して、このコピー プロセスを遅らせます。
比如:我们有一个很大的Collection,具体如hashtable,有很多客户端会并发同时访问它。其中一个特别的客户端要进行连续的数据获取,此时要求其他客户端不能再向hashtable中增加或删除 东东。
最直接的解决方案是:使用collection的lock,让这特别的客户端获得这个lock,进行连续的数据获取,然后再释放lock。
public void foFetches(Hashtable ht){ synchronized(ht){ //具体的连续数据获取动作.. } }
但是这一办法可能锁住Collection会很长时间,这段时间,其他客户端就不能访问该Collection了。
第二个解决方案是clone这个Collection,然后让连续的数据获取针对clone出来的那个Collection操作。这个方案前提是,这个Collection是可clone的,而且必须有提供深度clone的方法。Hashtable就提供了对自己的clone方法,但不是Key和value对象的clone。
public void foFetches(Hashtable ht){ Hashttable newht=(Hashtable)ht.clone(); }
问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了,那么对clone出来的对象操作就没有意义了。
最后解决方案:我们可以等其他客户端修改完成后再进行clone,也就是说,这个特别的客户端先通过调用一个叫clone的方法来进行一系列数据获取操作。但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象Collection。
使用Proxy实现这个方案,这就是copy-on-write操作。
Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用。
更多Java设计模式之代理模式(Proxy模式)介绍相关文章请关注PHP中文网!
相关文章: