ITPUB??ì3
12月微软Hyper-V虚拟化沙龙主题征集
ITPUB论坛 » Java企业开发 » 模式学习笔记

新一届的微软MVP评选已经开始,欢迎各位推荐!

标题: 模式学习笔记
离线 wlcdcy
初级会员



精华贴数 0
个人空间 0
技术积分 38 (34627)
社区积分 0 (703348)
注册日期 2005-11-29
论坛徽章:0
      
      

发表于 2008-9-16 11:30 
模式学习笔记

Design Pattern: Template Method and Strategy

两者皆属于行为模式,区别在于 模板模式通过继承来复写或者改变部分算法。更具有定制性。策略通过委托来改变和抽象算法,更具有灵活性。

模板模式

模板模式的目的:定义一个操作算法的骨架(通常调用自身【抽象类】中的抽象方法,或者其他对象方法)。将一些步骤延迟到子类中,使得子类不可以改变一个算法的结构,只能重定义该算法的特定步骤。

模板模式的参与者:
  • 抽象类:定义一系列的抽象方法,由具体的子类重定义,以实现一个算法的各个步骤。
  • 实现类:实现抽象方法,以完成算法中与特定子类相关的步骤。

模板模式是一种常用的模式。框架应用的基础模式之一。它展示了,一种经典的重用形式。但是有时吧通用算法和流程放置在父类中并不合理。模板模式提倡的继承复用具有非常强的定制性,使得子类和父类绑定子一起,在某些需要灵活性更强的场合,策略模式是更好的选择。


策略模式


策略模式的目的:定义一系列算法(通常采用接口现实),并把它们封装起来,并且是它们可以互相交换。该模式使得算法可以独立于它的客户而变化。


策略模式的参与者:

  • 策略(Strategy):定义所有支持的算法的公共接口,上下文中(Context)使用这个接口来调用某个具体的策略定义的算法。

  • 具体策略(ConcreteStrategy):实现策略接口的具体算法。

  • 上下文(Context):通常持有一个策略的引用,也可以持有一个策略对象引用的聚集。定义一系列客户接口方法,将客户请求委托给策略的算法实现。

策略模式减少了通用算法和具体控制细节的耦合,比模板模式复杂,但灵活性更强。再需要完全替换运算法则的情况下更适合,缺点是客户代码需要预先知道、并理解所使用策略的细节。



[ 本帖最后由 wlcdcy 于 2008-9-16 11:49 编辑 ]


只看该作者    顶部
在线/呼叫 Sky-Tiger
天王盖地虎


来自 Vancouver
精华贴数 39
个人空间 0
技术积分 164608 (3)
社区积分 47285 (15)
注册日期 2004-2-19
论坛徽章:293
现任管理团队成员ITPUB长老会成员Heart of PUB管理团队2007贡献徽章管理团队2006纪念徽章会员2007贡献徽章
会员2006贡献徽章开发板块每日发贴之星开发板块每日发贴之星生肖徽章2007版:蛇开发板块每日发贴之星开发板块每日发贴之星

发表于 2008-9-16 11:50 
GOOD! 继续!


__________________
-----孰能浊以静之徐清  孰能安以动之徐生-----  
-----风来疏竹  风过而竹不留声;雁照寒塘  雁去而塘不留影; 故君子事来而心始现  事去而心随空----

----------------
Groovy 研究中...
JAX-WS20(finished)/CXF/ESB/BPEL 研究中...
EJB3(finished)/Hibernate3 研究中...
OSGI/KnopflerFish 研究中...
JBOSS Seam2.0/JSF/AJAX(finished)/ICEFace/ZKoss/Flex3 研究中...
Mysql 研究中...
Spring2.5  研究中...
Blog/Wiki/RSS/ATOM 研究中...
只看该作者    顶部
离线 wlcdcy
初级会员



精华贴数 0
个人空间 0
技术积分 38 (34627)
社区积分 0 (703348)
注册日期 2005-11-29
论坛徽章:0
      
      

发表于 2008-9-16 17:06 
代理模式(design pattern : proxy)

代理模式属于结构模式,其目的是为其对象提供一种代理,以控制对这个对象的访问。代理模式的用途非常广泛,如下一些场景
  • 在网络环境下,使用远程代理(romote proxy)对客户隐藏网络通信细节,使得客户可以透明的进行网络操作,就如同本地操作一样.
  • 一个可在文档中嵌入图形对象的文本编辑器(如word),有些图形对象的创建开销很大,但是打开文档必须很快速,因此在打开文档时要避免一次性创建所有开销大的对象。以为所有这些对象并不是同时可见的,所以也没有必要同时创建这些对象,这时候可以引入虚拟代理(virtual proxy)来代替那个真正的图形,只有文档编辑器激活图形代理的draw操作时,图形代理才真正的创建这个图形。
  • 通过代理,拦截对真是对象的访问,以实现一些附加的处理,如前处理和后处理等,这也是一种经典aop代理的实现手法。
  • 代理模式也是隔离一些和业务无关的数据库具体操作的好方法。
代理模式参与者:
  • 代理(proxy):持有一个实体的引用,使得代理可以访问实体;提供一个与目标(subject)的接口相同的接口,使代理可以替代实体;控制对实体的存取,负责创建和删除它,其他功能依赖与上述提到的代理的类型。
  • 目标(subject):定义真实目标(realsubject)和代理(proxy)的公共接口,在任何使用realsubject的地方都可以使用proxy。
  • realsubject:定义代理(proxy)所代表的实体。
普通代理、code


-------目标类-------
public abstract class Subject {
  abstract public void operation();
}


-------目标实现类------
public class RealSubject extends Subject {
  public void operation() {
   System.out.println("this is operation");
  }
}


-------代理类-------
public class Proxy extends Subject {
  /**
* 持有一个实体引用使得代理可以访问实体
*/
  private Subject subject;
  
  /* (non-Javadoc)
* @see Subject#operation()
* 实现父类的抽象方法,控制对实体的存取,负责创建和删除
*/
  public void operation() {
   this.beforeOperation();
   if(subject==null){
    subject= new RealSubject();
   }
   subject.operation();
   this.afterOperation();
  }
  /**
* 在operation之前执行。前操作
*/
  public void beforeOperation() {
   System.out.println("before do something");
  }
  /**
* 在operation之后执行。后操作
*/
  public void afterOperation() {
   System.out.println("after do something");
  }
  /**使用抽象实体来初始化代理对象
* @param subject
*/
  public Proxy(Subject subject) {
   this.subject=subject;
  }
  /**测试方法
* @param args
*/
  public static void main(String[] args){
   Subject subject = new Proxy(new RealSubject());
   subject.operation();
}
}

-----------------测试结果----------------

before do something
this is operation
after do something


动态代理、

虚拟代理


只看该作者    顶部
离线 權寶兒
閃舞精靈


来自 天堂
精华贴数 0
个人空间 0
技术积分 263 (7500)
社区积分 717 (1180)
注册日期 2008-3-13
论坛徽章:6
2008北京奥运纪念徽章:乒乓球生肖徽章2007版:鼠    
      

发表于 2008-9-18 15:07 
受教


__________________
☆┏┅◆ ·。 ◢◣◢◣  。· ◇┅┓★
あ┇ 纞   ·  。【權寶兒】 。· love┇あ
ぃ◇┅→→→→◥◤绝*恋←←←←┅◆ぃ
★╧ぁ愛我所愛↓◥◤ ↑い無怨無悔╧☆
----------------------------------------------
you do not keep anything for a special occasion.
because every day that you live is a special occasion.
----------------------------------------------
不要呼叫我,打不开链接
---------------------------------------------
老鼠要到了,还是好人多
只看该作者    顶部
在线/呼叫 Sky-Tiger
天王盖地虎


来自 Vancouver
精华贴数 39
个人空间 0
技术积分 164608 (3)
社区积分 47285 (15)
注册日期 2004-2-19
论坛徽章:293
现任管理团队成员ITPUB长老会成员Heart of PUB管理团队2007贡献徽章管理团队2006纪念徽章会员2007贡献徽章
会员2006贡献徽章开发板块每日发贴之星开发板块每日发贴之星生肖徽章2007版:蛇开发板块每日发贴之星开发板块每日发贴之星

发表于 2008-9-18 20:38 
楼主,继续!


__________________
-----孰能浊以静之徐清  孰能安以动之徐生-----  
-----风来疏竹  风过而竹不留声;雁照寒塘  雁去而塘不留影; 故君子事来而心始现  事去而心随空----

----------------
Groovy 研究中...
JAX-WS20(finished)/CXF/ESB/BPEL 研究中...
EJB3(finished)/Hibernate3 研究中...
OSGI/KnopflerFish 研究中...
JBOSS Seam2.0/JSF/AJAX(finished)/ICEFace/ZKoss/Flex3 研究中...
Mysql 研究中...
Spring2.5  研究中...
Blog/Wiki/RSS/ATOM 研究中...
只看该作者    顶部
离线 wlcdcy
初级会员



精华贴数 0
个人空间 0
技术积分 38 (34627)
社区积分 0 (703348)
注册日期 2005-11-29
论坛徽章:0
      
      

发表于 2008-9-20 11:05 
前两天精神不太好,没什么心情做事,浪费了宝贵的2天时间,今天感觉还不错就继续学习。赶快吧失去的时间找回来。闲话少说,进入正题。。。

动态代理

所谓动态代理就是代理的实现的方式上的不同吧。不用为每一个目标对象实现单独的代理,对需要相同代理的目标对象显示一个集中代理。这样大大的减少了开发工作量。代理功能集中,易于维护。这是我个人的理解。若大家有其他理解可以畅所欲言。

动态代理最重要的是使用了java的反射机制。

自己可以通过反射去对上面的代码重构实现一个动态的代理。

也可以去实现jdk中提供的InvocationHandler接口就可以了。

下面看看代理类的实现

----------------------------动态代理类-----------------

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynaProxy implements InvocationHandler {
/**
  * 代理目标对象
  */
private Object proxyObj;
public DynaProxy(Object obj){
  proxyObj=obj;
}
/**静态方法。通过反射生成动态代理
  * @param obj
  * @return
  */
public static Object make(Object obj){
  Class clazz=obj.getClass();
  //使用特定的代理工厂来生成对象代理
  return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),new DynaProxy(obj));
}

/* (non-Javadoc)
  * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
  * 截获所有对象的方法调用,提供一个前置处理和后处理
  */
public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  this.beforeInvoke(method);
  //Object object=
  method.invoke(proxyObj, args);
  this.afterInvoke(method);
  return null;
}

   /**
  * 在operation之前执行。前操作
  */
   public void beforeInvoke(Method method) {
    System.out.println("before do something");
   }
   /**
  * 在operation之后执行。后操作
  */
   public void afterInvoke(Method method) {
    System.out.println("after do something");
   }

/**
  * @param args
  */
public static void main(String[] args) {
  //测试对Subject1,Subject2对象代理
  Subject1 sub1 = (Subject1) DynaProxy.make(new RealSubject1());  
  sub1.operation1();
  Subject2 sub2 = (Subject2) DynaProxy.make(new RealSubject2());
  sub2.operation2();
}
}

-----------目标接口1---------------------------
public interface Subject1 {
public void operation1();
}

-----------目标接口1现实--------------------------
public class RealSubject1 implements Subject1 {
public void operation1() {
  System.out.println("this is Subject1 operation1");
}
}

-------------目标接口2------------------------
public interface Subject2 {
public void operation2();
}

-------------目标接口2实现-------------------
public class RealSubject2 implements Subject2 {
public void operation2() {
  System.out.println("this is Subject2 operation2");
}
}


------------------------测试结果----------------


before do something
this is Subject1 operation1
after do something
before do something
this is Subject2 operation2
after do something


从代码中可以看出,两个目标接口的定义是不同的,一个是public void operation1() 一个是public void operation2() ,如果采用普通代理实现,那必然要为他们分别实现代理类,即使他们代理类中的工作是相同的。可见,采用动态代理可以减少开发代码工作量。使所有需要相同操作的对象采用同一个代理类集中处理,而且维护上也相对要容易很多。

[ 本帖最后由 wlcdcy 于 2008-9-20 11:35 编辑 ]


只看该作者    顶部
离线 wlcdcy
初级会员



精华贴数 0
个人空间 0
技术积分 38 (34627)
社区积分 0 (703348)
注册日期 2005-11-29
论坛徽章:0
      
      

发表于 2008-9-22 10:40 
学习过代理模式。让我们再来看一下适配器模式(Adapter),它与代理模式都属于结构模式

在代理模式中可以看到一些

经常会将两个没有关系的类组合起来一起使用,如果你不是最初的设计者,没有源码可以修改;或者既是你有源码。可是你不愿意为了这一个组合应用去修改接口,或者说接口不能修改。因为他在很多地方 一定被使用。如果你修改了接口那将是一个灾难。使用适配器就可以做到让他们混合使用。

举个例子,你家里的输出插座是个3相插口的,而你的台灯确实2相插头,它们是不能混用的。你又必须使用台灯,我想你肯定不会把3相插口拿掉然后换装一个2相插口来使用台灯吧,其实你也不能能去替换。因为你家里还有其它的电器是3相插头的。你只有去买一个插板来转换一下了。

其实这就是一个适配器的模式。插板就是一个适配器。


适配器模式参与者:

被适配者(Adaptee):也就是需要使用的对象。改对象是我们不能掌控的,也就是不可改变的(2相插头)
目标(Target):也就是需要使用适配者一起协同工作的对象,该对象是我们可以掌控的。(3相插口)
适配器(Adaptor):是将被适配者和目标组合在一起使得它们可以一起使用。(插板)


下面看看代码的实现:


-----------------2相插头接口----------------
public interface TwoPlug {
  public void twoOperation();
}


-----------------2相插头接口的实现类----------------
public class TwoPlugImpl implements TwoPlug {
  /* (non-Javadoc)
* @see TwoPlug#twoOperation()
* 需要2项插口
*/
public void twoOperation() {
   System.out.println("插到插口,接上电源开始工作了。。。");
  }
}


-----------------3相插头接口----------------
public interface ThreeJack {
  public void threeOperation();
}


-----------------3相插头接口的实现类----------------
public class ThreeJackImpl implements ThreeJack {
  /* (non-Javadoc)
* @see ThreeJack#threeOperation()
* 插入3相插头,
*/
public void threeOperation() {
   System.out.println("插入插头,开始供电了。。。");
  }
}

-----------------适配器的实现----------------
public class AdapterThreeJack implements ThreeJack {
  private TwoPlug twoPlug;
  public AdapterThreeJack(TwoPlug twoPlug){
   this.twoPlug=twoPlug;
  }
  /* (non-Javadoc)
* @see ThreeJack#threeOperation()
* 实现这个接口,使得两个对象在不修改接口的情况下可以一起工作。
*/
  public void threeOperation() {
   this.twoPlug.twoOperation();
  }
public static void main(String [] args){
  new AdapterThreeJack(new TwoPlugImpl()).threeOperation();
}
}

-----------------测试结果----------------

插到插口,接上电源开始工作了。。。


从代码可以看出,。适配器只要使用了java的继承和组合技术。。

实现目标接口,并将被适配对象作为他的一个成员。这样可以随便使用它里面的方法。使得目标和被适配者一起工作。


只看该作者    顶部
在线/呼叫 justforregister
SAP


精华贴数 1
个人空间 10
技术积分 44005 (17)
社区积分 12789 (120)
注册日期 2005-6-10
论坛徽章:116
现任管理团队成员     
      

发表于 2008-9-22 11:31 
nice job


__________________
只看该作者    顶部
 
    

相关内容


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问