知识大全 设计模式分解java(2)

Posted 部件

篇首语:困难是人的教科书。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 设计模式分解java(2)相关的知识,希望对你有一定的参考价值。

  当然也可以结合工厂模式来创建AbstractSpoon实例

  在Java中Prototype模式变成clone()方法的使用 由于Java的纯洁的面向对象特性

  使得在Java中使用设计模式变得很自然 两者已经几乎是浑然一体了 这反映在很多模式上 如Interator遍历模式

  /** */

  创建模式 Builder

  Builder模式定义:

  将一个复杂对象的构建与它的表示分离 使得同样的构建过程可以创建不同的表示

  Builder模式是一步一步创建一个复杂的对象 它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们

  用户不知道内部的具体构建细节 Builder模式是非常类似抽象工厂模式

  细微的区别大概只有在反复使用中才能体会到

  为何使用?

  是为了将构建复杂对象的过程和它的部件解耦 注意: 是解耦过程和部件

  因为一个复杂的对象 不但有很多大量组成部分 如汽车 有很多部件:车轮 方向盘 发动机还有各种小零件等等

  部件很多 但远不止这些 如何将这些部件装配成一辆汽车 这个装配过程也很复杂(需要很好的组装技术)

  Builder模式就是为了将部件和组装过程分开

  如何使用?

  首先假设一个复杂对象是由多个部件组成的 Builder模式是把复杂对象的创建和部件的创建分别开来

  分别用Builder类和Director类来表示

  首先 需要一个接口 它定义如何创建复杂对象的各个部件:

  public interface Builder

  //创建部件A  比如创建汽车车轮

  void buildPartA();

  //创建部件B 比如创建汽车方向盘

  void buildPartB();

  //创建部件C 比如创建汽车发动机

  void buildPartC();

  //返回最后组装成品结果 (返回最后装配好的汽车)

  //成品的组装过程不在这里进行 而是转移到下面的Director类中进行

  //从而实现了解耦过程和部件

  Product getResult();

  

  用Director构建最后的复杂对象 而在上面Builder接口中封装的是如何创建一个个部件

  (复杂对象是由这些部件组成的) 也就是说Director的内容是如何将部件最后组装成成品:

  public class Director

  private Builder builder;

  public Director( Builder builder )

  this builder = builder;

  

  // 将部件partA partB partC最后组成复杂对象

  //这里是将车轮 方向盘和发动机组装成汽车的过程

  public void construct()

  builder buildPartA();

  builder buildPartB();

  builder buildPartC();

  

  

  Builder的具体实现ConcreteBuilder:

  通过具体完成接口Builder来构建或装配产品的部件;

  定义并明确它所要创建的是什么具体东西;

  提供一个可以重新获取产品的接口:

  public class ConcreteBuilder implements Builder

  Part partA partB partC;

  public void buildPartA()

  //这里是具体如何构建partA的代码

  ;

  public void buildPartB()

  //这里是具体如何构建partB的代码

  ;

  public void buildPartC()

  //这里是具体如何构建partB的代码

  ;

  public Product getResult()

  //返回最后组装成品结果

  ;

  

  复杂对象:产品Product:

  public interface Product

  复杂对象的部件:

  public interface Part

  我们看看如何调用Builder模式:

  ConcreteBuilder builder = new ConcreteBuilder();

  Director director = new Director( builder );

  nstruct();

  Product product = builder getResult();

  Builder模式的应用

  在Java实际使用中 我们经常用到 池 (Pool)的概念 当资源提供者无法提供足够的资源

  并且这些资源需要被很多用户反复共享时 就需要使用池

   池 实际是一段内存 当池中有一些复杂的资源的 断肢 (比如数据库的连接池 也许有时一个连接会中断)

  如果循环再利用这些 断肢 将提高内存使用效率 提高池的性能

  修改Builder模式中Director类使之能诊断 断肢 断在哪个部件上 再修复这个部件

  /** */

  创建模式 Singleton

  定义:

  Singleton模式主要作用是保证在Java应用程序中 一个类Class只有一个实例存在

  在很多操作中 比如建立目录 数据库连接都需要这样的单线程操作

  还有 singleton能够被状态化; 这样 多个单态类在一起就可以作为一个状态仓库一样向外提供服务 比如 你要论坛中的帖子计数器 每次浏览一次需要计数 单态类能否保持住这个计数 并且能synchronize的安全自动加 如果你要把这个数字永久保存到数据库 你可以在不修改单态接口的情况下方便的做到

  另外方面 Singleton也能够被无状态化 提供工具性质的功能

  Singleton模式就为我们提供了这样实现的可能 使用Singleton的好处还在于可以节省内存 因为它限制了实例的个数 有利于Java垃圾回收(garbage collection)

  我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的 因为被装入的类实际也属于资源

  如何使用?

  一般Singleton模式通常有几种形式:

  public class Singleton

  private Singleton()

  //在自己内部定义自己一个实例 是不是很奇怪?

  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法 可以直接访问

  public static Singleton getInstance()

  return instance;

  

  

  第二种形式:

  public class Singleton

  private static Singleton instance = null;

  public static synchronized Singleton getInstance()

  //这个方法比上面有所改进 不用每次都进行生成对象 只是第一次

  //使用时生成实例 提高了效率!

  if (instance==null)

  instance=new Singleton();

  return instance;   

  

  使用Singleton getInstance()可以访问单态类

  上面第二中形式是lazy initialization 也就是说第一次调用时初始Singleton 以后就不用再生成了

  注意到lazy initialization形式中的synchronized 这个synchronized很重要 如果没有synchronized 那么使用 getInstance()是有可能得到多个Singleton实例 关于lazy initialization的Singleton有很多涉及double checked locking (DCL)的讨论 有兴趣者进一步研究

  一般认为第一种形式要更加安全些

  使用Singleton注意事项

  有时在某些情况下 使用Singleton并不能达到Singleton的目的 如有多个Singleton对象同时被不同的类装入器装载 在EJB这样的分布式系统中使用也要注意这种情况 因为EJB是跨服务器 跨JVM的

  我们以SUN公司的宠物店源码(Pet Store )的ServiceLocator为例稍微分析一下

  在Pet Store中ServiceLocator有两种 一个是EJB目录下 一个是WEB目录下 我们检查这两个ServiceLocator会发现内容差不多 都是提供EJB的查询定位服务 可是为什么要分开呢?仔细研究对这两种ServiceLocator才发现区别 在WEB中的 ServiceLocator的采取Singleton模式 ServiceLocator属于资源定位 理所当然应该使用Singleton模式 但是在EJB中 Singleton模式已经失去作用 所以ServiceLocator才分成两种 一种面向WEB服务的 一种是面向EJB服务的

  Singleton模式看起来简单 使用方法也很方便 但是真正用好 是非常不容易 需要对Java的类 线程 内存等概念有相当的了解

  /** */

  结构模式 Facade

  Facade的定义: 为子系统中的一组接口提供一个一致的界面

  Facade一个典型应用就是数据库JDBC的应用 如下例对数据库的操作:

  public class DBCompare

  Connection conn = null;

  PreparedStatement prep = null;

  ResultSet rset = null;

  try

  Class forName( <driver> ) newInstance();

  conn = DriverManager getConnection( <database> );

  String sql = SELECT * FROM <table> WHERE <column name> = ? ;

  prep = conn prepareStatement( sql );

  prep setString( <column value> );

  rset = prep executeQuery();

  if( rset next() )

  System out println( rset getString( <column name ) );

  

   catch( SException e )

  e printStackTrace();

   finally

  rset close();

  prep close();

  conn close();

  

  

  上例是Jsp中最通常的对数据库操作办法

  在应用中 经常需要对数据库操作 每次都写上述一段代码肯定比较麻烦 需要将其中不变的部分提炼出来 做成一个接口 这就引入了facade外观对象 如果以后我们更换Class forName中的<driver>也非常方便 比如从Mysql数据库换到Oracle数据库 只要更换 facade接口中的driver就可以

  我们做成了一个Facade接口 使用该接口 上例中的程序就可以更改如下:

  public class DBCompare

  String sql = SELECT * FROM <table> WHERE <column name> = ? ;

  try

  Mysql msql=new mysql(sql);

  prep setString( <column value> );

  rset = prep executeQuery();

  if( rset next() )

  System out println( rset getString( <column name ) );

  

   catch( SException e )

  e printStackTrace();

   finally

  mysql close();

  mysql=null;

  

  

  可见非常简单 所有程序对数据库访问都是使用改接口 降低系统的复杂性 增加了灵活性

  如果我们要使用连接池 也只要针对facade接口修改就可以

  facade实际上是个理顺系统间关系 降低系统间耦合度的一个常用的办法

  也许你已经不知不觉在使用 尽管不知道它就是facade

  /** */

  结构模式 Proxy

  Proxy是比较有用途的一种模式 而且变种较多 应用场合覆蓋从小结构到整个系统的大结构

  Proxy是代理的意思 我们也许有代理服务器等概念

  代理概念可以解释为:在出发点到目的地之间有一道中间层 意为代理

  设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问

  为什么要使用Proxy?

   授权机制 不同级别的用户对同一对象拥有不同的访问权利

  如Jive论坛系统中 就使用Proxy进行授权机制控制

  访问论坛有两种人:注册用户和游客(未注册用户)

  Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限

   某个客户端不能直接操作到某个对象 但又必须和那个对象有所互动

  举例两个具体情况:

  ( )如果那个对象是一个是很大的图片 需要花费很长时间才能显示出来

  那么当这个图片包含在文档中时 使用编辑器或浏览器打开这个文档 打开文档必须很迅速

  不能等待大图片处理完成 这时需要做个图片Proxy来代替真正的图片

  ( )如果那个对象在Internet的某个远端服务器上

  直接操作这个对象因为网络速度原因可能比较慢 那我们可以先用Proxy来代替那个对象

  总之原则是 对于开销很大的对象 只有在使用它时才创建 这个原则可以为我们节省很多宝贵的Java内存

  所以 有些人认为Java耗费资源内存 我以为这和程序编制思路也有一定的关系

  如何使用Proxy?

  以Jive论坛系统为例 访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客

  注册普通用户才能发言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等

  这些权限划分和管理是使用Proxy完成的

  Forum是Jive的核心接口 在Forum中陈列了有关论坛操作的主要行为 如论坛名称

  论坛描述的获取和修改 帖子发表删除编辑等

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

  public class ForumPermissions implements Cacheable

  /** Permission to read object */

  public static final int READ = ;

  /** Permission to administer the entire sytem */

  public static final int SYSTEM_ADMIN = ;

  /** Permission to administer a particular forum */

  public static final int FORUM_ADMIN = ;

  /** Permission to administer a particular user */

  public static final int USER_ADMIN = ;

  /** Permission to administer a particular group */

  public static final int GROUP_ADMIN = ;

  /** Permission to moderate threads */

  public static final int MODERATE_THREADS = ;

  /** Permission to create a new thread */

  public static final int CREATE_THREAD = ;

  /** Permission to create a new message */

  public static final int CREATE_MESSAGE = ;

  /** Permission to moderate messages */

  public static final int MODERATE_MESSAGES = ;

  

  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是个名副其实的 网关 安全代理系统

cha138/Article/program/Java/gj/201311/27593

相关参考

知识大全 JAVA设计模式之事务处理[2]

JAVA设计模式之事务处理[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!importjava

知识大全 关于Java23种设计模式的有趣见解[2]

关于Java23种设计模式的有趣见解[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  装饰模

知识大全 从追MM谈Java的23种设计模式[2]

经典:从追MM谈Java的23种设计模式[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  桥

知识大全 为JAVA性能而设计(2)

为JAVA性能而设计(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  作者eclipse  

知识大全 Java程序性能优化-享元模式(2)[2]

Java程序性能优化-享元模式(2)[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  pub

知识大全 Java程序性能优化-业务代理模式(2)[2]

Java程序性能优化-业务代理模式(2)[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  i

知识大全 Java程序性能优化-代理模式(2)

Java程序性能优化-代理模式(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!   

知识大全 Java程序性能优化-观察者模式(2)[2]

Java程序性能优化-观察者模式(2)[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  图&

知识大全 Java程序性能优化-Value Object模式(2)[2]

Java程序性能优化-ValueObject模式(2)[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看

知识大全 Java程序性能优化-单例模式(2)

Java程序性能优化-单例模式(2)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!