The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

#

说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者都吃饱撑着没事做吗?

再谈Comparator接口之前,大家应该先了解一个叫“策略模式”的东东。一下是百度百科对策略模式的描写:

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)

 

之所以要谈到策略模式,就是因为Comparator接口其实就是一种策略模式的实践。实现Comparator接口的类必然就会实现一个compareTo(Object o1, Object o2)的方法,而这个方法就是算法中的一部分,所有使用了compareTo方法的类都不会关心compareTo是如何工作的,只关心他的返回值,这也是面向对象中著名的封装特性。

那Comparator接口应该如何使用呢?别急,首先我们要先对Person类进行一下处理,因为我们现在使用Comparator接口,所以Comparable接口就可以光荣的退休了:

   1: public class Person {
   2:  
   3:     private String name;
   4:     private int age;
   5:     
   6:     public Person() {
   7:         
   8:     }
   9:     
  10:     public Person(String name, int age) {
  11:         this.name = name;
  12:         this.age = age;
  13:     }
  14:  
  15:     public String getName() {
  16:         return name;
  17:     }
  18:  
  19:     public void setName(String name) {
  20:         this.name = name;
  21:     }
  22:  
  23:     public int getAge() {
  24:         return age;
  25:     }
  26:  
  27:     public void setAge(int age) {
  28:         this.age = age;
  29:     }
  30:  
  31:     @Override
  32:     public String toString() {
  33:         return "Person [age=" + age + ", name=" + name + "]";
  34:     }
  35:  
  36: }

新建一个实现Comparator的实现类PersonComparator:

   1: import java.util.Comparator;
   2:  
   3: public class PersonComparator implements Comparator<Person> {
   4:  
   5:     @Override
   6:     public int compare(Person p1, Person p2) {
   7:         if (p1.getAge() > p2.getAge()) {
   8:             return 1;
   9:         } else if (p1.getAge() < p2.getAge()) {
  10:             return -1;
  11:         }
  12:         return 0;
  13:     }
  14:     
  15: }

然后再用回我们的CompareTest做测试:

   1: import java.util.Arrays;
   2:  
   3: public class CompareTest {
   4:  
   5:     public static void main(String[] args) {
   6:         Person[] persons = {
   7:                 new Person("P1", 60),
   8:                 new Person("P2", 20),
   9:                 new Person("P3", 40)
  10:         };
  11:         
  12:         System.out.println(Arrays.toString(persons));
  13:         
  14:         Arrays.sort(persons, new PersonComparator());
  15:         
  16:         System.out.println(Arrays.toString(persons));
  17:     }
  18:  
  19: }

注意:在上面的sort方法中,我们传进了一个PersonComparator的实例对象作为参数,读者也可以试试不传入这个参数,看是否能正确工作。

结果当然是跟上面演示的例子一样啦,我就不再重复了。

posted @ 2011-04-12 12:26 Eric_jiang 阅读(3578) | 评论 (0)编辑 收藏

新建一个文本文档,在其中输入以下内容:
DirectShowSource("E:\FreeLoop.wmv")
LoadPlugin("C:\Program Files\Easy RealMedia Tools\common\VSFilter.dll")
TextSub("E:\FreeLoop.srt")

第1行是指定视频文件路径,你可以根据自己文件的具体位置进行修改。第2行是VobSub滤镜插件的文件路径,第3行是字幕文件的路径,同样根据具体位置修改。将文件保存为FreeLoop.avs,文件名任意,但扩展名必须是avs。
第三步:启动Easy RealMedia Producer,将弹出设置窗口,将“select language”设置为“简体中文”,点击“确定”进入软件主界面。单击“添加”按钮,添加上面保存的FreeLoop.avs。


第四步:双击任务出现RealMedia编码设置窗口,按需设置好音视频码率,下面可以输入剪辑信息,输入好后点击“确定”返回主界面。
第五步:最后点击左下角的“开始压缩”,等待压缩完成即可。完成后打开压缩好的FreeLoop.rmvb文件,就可以看到带有字幕的MV了!用这种方法添加字幕,简单方便,而且支持文件类型众多,事实上很多电影添加字幕也是这样压制成的。

posted @ 2011-02-17 13:09 Eric_jiang 阅读(941) | 评论 (1)编辑 收藏

import java.io.*; 
public class ClassVersionChecker { 
public static void main(String[] args) throws IOException { 
   
for (int i = 0; i < args.length; i++) 
        checkClassVersion
(args[i]); 
} 
 
   
private static void checkClassVersion(String filename) 
       
throws IOException 
   
{ 
       
DataInputStream in = new DataInputStream 
         
(new FileInputStream(filename)); 
 
       
int magic = in.readInt(); 
       
if(magic != 0xcafebabe) { 
         
System.out.println(filename + " is not a valid class!");; 
       
} 
       
int minor = in.readUnsignedShort(); 
       
int major = in.readUnsignedShort(); 
       
System.out.println(filename + ": " + major + " . " + minor); 
       
in.close(); 
   
} 
} 

The possible values are :

major  minor Java platform version  
45       3           1.0 
45       3           1.1 
46       0           1.2 
47       0           1.3 
48       0           1.4 
49       0           1.5 
50       0           1.6 
posted @ 2010-12-10 17:42 Eric_jiang 阅读(261) | 评论 (3)编辑 收藏

import java.io.FileInputStream;

public class JavaVersionUtil {

 private static final String str = "C://a.class";
 // 版本号对应:
 // 5.0
 // 版本号(version):49.0
 // 6.0
 // 版本号(version):50.0
 // 1.4
 // 版本号(version):46.0
 // 1.3
 // 版本号(version):45.3

 public static void main(String args[]) {
  try {
   // 读取文件数据,文件是当前目录下的First.class
   FileInputStream fis = new FileInputStream(str);
   int length = fis.available();
   // 文件数据
   byte[] data = new byte[length];
   // 读取文件到字节数组
   fis.read(data);
   // 关闭文件
   fis.close();
   // 解析文件数据
   parseFile(data);
  } catch (Exception e) {
   System.out.println(e);
  }
 }

 private static void parseFile(byte[] data) {
  // 输出魔数
  System.out.print("魔数(magic):0x");
  System.out.print(Integer.toHexString(data[0]).substring(6)
    .toUpperCase());
  System.out.print(Integer.toHexString(data[1]).substring(6)
    .toUpperCase());
  System.out.print(Integer.toHexString(data[2]).substring(6)
    .toUpperCase());
  System.out.println(Integer.toHexString(data[3]).substring(6)
    .toUpperCase());
  // 主版本号和次版本号码
  int minor_version = (((int) data[4]) << 8) + data[5];
  int major_version = (((int) data[6]) << 8) + data[7];
  System.out.println("版本号(version):" + major_version + "."
    + minor_version);
 }

}

posted @ 2010-11-11 13:12 Eric_jiang 阅读(651) | 评论 (0)编辑 收藏

一个java的class文件是一个二进制文件,其中前四个字节是magic位,第五到第六个字节对应于minor和major,下面是这个类文件版本与JDK的对应关系。class文件的minor和major可以通过ultraedit来查看,或自己编程等。
major minor Java platform version
45 3 1.0
45 3 1.1
46 0 1.2
47 0 1.3
48 0 1.4
49 0 1.5
50 0 1.6
posted @ 2010-11-11 13:11 Eric_jiang 阅读(806) | 评论 (0)编辑 收藏

一直在tomcat服务器上做开发,客户要求部署到TongWeb服务器上,并且要求JDK版本为1.4.2。把WEB应用部署到TongWeb上,本来在tomcat正常的运行的程序在TongWeb上出现了java.lang.UnsupportedClassVersionError异常。

TongWeb的JSP容器也是Tomcat呀。应该不会出现这样的问题。原因是什么呢?G一下。找到了原因。总结如下:

出现java.lang.UnsupportedClassVersionError 错误的原因,是因为我们使用高版本的JDK编译的Java class文件试图在较低版本的JVM上运行,所报的错误。

因为,高版本的JDK生成的class文件使用的格式,可能与低版本的JDK的.class文件格式不同。这样,低版本的JVM无法解释执行这个.class文件,会抛出java.lang.UnsupportedClassVersionError不支持的Class版本错误。

这个错误尤其在JDK5与JDK5之前的版本上表现明显。因为,JDK5在Java语法上作了不少增强,引入了一些新的.class文件的元素,导致旧版本的JVM无法解释、执行.class文件。即使这个类并没有使用任何JDK5的新元素,但是JDK5生成的.class文件,JDK1.4及其以前的JVM都无法辨认!

所以,目前使用最广的,还是JDK1.4。很多软件和项目都无法使用JDK5。

有一个名叫 Toby Reyelts 的开发人员决定消除 JDK 5.0 编译器限制。结果就是开放源代码的 Retroweaver 项目(参见 参考资料)。Retroweaver 使用 classworking 技术来修改由 JDK 5.0 编译器生成的二进制类表示,以便这些类可以与早期的 JVM 一起使用。

它通过修改JDK5生成的.class文件,将其变为JVM1.4及之前版本能够运行的.class文件。

目前,使用新版本的IDE编译程序可能会造成你遭遇java.lang.UnsupportedClassVersionError 错误。

比如,Eclipse3.3+MyEclipse6.5这个新版的IDE工具。进入首选项---Java---编译器,可以看到,默认的编译器依从等级是5.0,这里改为1.4,因为我们使用的软件需要运行在JDK1.4的JVM上。

步骤:项目点右键-->Properties-->Java Compiler-->将Enable project specific settings前的勾去掉-->Compiler compiliance level选择你想要的版本

在MyEclipse----应用服务器下,指定Tomcat5。指定Tomcat使用jdk1.4。

这样,就全部指定使用Jdk1.4来编译和运行程序了。如果全部指定jdk5也是可以的。但是,绝对不能够使用jdk5编译程序,而又在jdk1.4上运行程序,那样将会抛出java.lang.UnsupportedClassVersionError不支持的Class版本错误。反之,则可以。

这种情况下,不论是Eclipse生成的war包,还是ant文件生成war包,都使用jdk5编译,就会在运行时出现错误,该应用程序将无法启动。如果你查看Tomcat的日志文件,将会看到正是java.lang.UnsupportedClassVersionError错误发生了!

经验:以后做开发,如果可能的话,尽量使用JDK1.4,1.5来编译源程序,不要使用JDK过高版本的特性,以保持较好的移植性和兼容性。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaojianpitt/archive/2008/09/11/2913094.aspx

posted @ 2010-11-11 11:16 Eric_jiang 阅读(944) | 评论 (0)编辑 收藏

WebLogic Server 8,9,10破解补丁下载

WebLogic Server

       Server 是一个很优秀的商业中间件,但是价格昂贵!!!

       其实从官网下载下来WebLogic Server 是全功能版的,但是有5个IP的限制,也就是说只能有5以下的
今天无意中找到了破解这个限制的补丁,很全,8,9,10都有,很爽吧!!!破解的方法在压缩包中的readme.txt,参照上面的操作就可以了,我已经试验过8的的确有效,哪位兄弟有条件的可以帮我测试一下9和10是否有效。

      weblogic.8.1.crack.rar

      weblogic.9.2.crack.zip

      weblogic.10.crack.zip

     请参照readme.txt中的破解说明!!!
weblogic 10.0破解版使用说明:
今天看了一下版本10,算法没变,只是验证文件位置变了,老方法,测试了一下,OK!!!
1.将license.bea和weblog_crack.jar拷贝到bea安装目录下,例如d:\bea
2.修改d:\bea\user_projects\domains\odpsdomain(你建立的域)\bin\startWeblogic.cmd
修改
set CLASSPATH=%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSP

set CLASSPATH=d:\bea\weblogic_crack.jar;%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSP
3. 重启weblogic

另附weblogic 10的下载地址

http://download2.bea.com/pub/platform/100/server100_win32.exe


posted @ 2010-11-01 22:55 Eric_jiang 阅读(1364) | 评论 (0)编辑 收藏

具体元素的接口与实现类

public interface Person {
      void accept(Visitor visitor);
}


public class Woman implements Person{

    public void accept(Visitor visitor) {
          visitor.visit(this);
    }
}


public class Man implements Person{

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}



访问者接口与实现类,分别代表男人与女人在不同的状态下的表现

public interface Visitor {
      public void visit(Man man);
      public void visit(Woman girl);
}

//成功时Man与Woman的不同表现
public class Success implements Visitor{

    public void visit(Man man) {
        System.out.println("当男人成功时,背后多半有一个伟大的女人");
    }


    public void visit(Woman woman) {
        System.out.println("当女人成功时,背后大多有一个不成功的男人");
    }
}

//恋爱时Man与Woman的不同表现
public class Love implements Visitor{

    public void visit(Man man) {
        System.out.println("当男人恋爱时,凡事不懂也装懂");
    }


    public void visit(Woman girl) {
        System.out.println("当女人恋爱时,遇事懂也装不懂");
    }
}



ObjectStructure与客户端测试代码

import java.util.*;

public class ObjectStructure {
    private List<Person> elements = new ArrayList<Person>();

    public void attach(Person element){
        elements.add(element);
    }
   
    public void detach(Person element){
        elements.remove(elements);
    }
   
    //遍历各种具体元素并执行他们的accept方法
    public void display(Visitor visitor){
        for(Person p:elements){
            p.accept(visitor);
        }
    }
}


public class Client {
      public static void main(String[] args) {
        ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure
        //实例化具体元素
        o.attach(new Man()); 
        o.attach(new Woman());
       
        //当成功时不同元素的不同反映
        Visitor success = new Success();           //依赖于抽象的Visitor接口
        o.display(success);
       
        //当恋爱时的不同反映
        Visitor amativeness = new Love();          //依赖于抽象的Visitor接口
        o.display(amativeness);
       
    }
}



需求的变化

假设现在需求要扩展数据结构,增加一种具体元素,男与女之外的一种不明物体,我们暂时把它称为“怪兽”,在既有访问者模式的架构下,应该怎样?首先增加一个Bruce类,实现Person接口。最麻烦的是要修改访问者接口及其所有具体访问者!

  因为Visit方法中没有包含访问Bruce对象的行为,因此我们被迫要去手工更改Visitor(包括抽象的,具体的),在其中添加有关Bruce对象的行为,这严重违反了“开放-封闭”原则。究其原因在于目前的结构下,被访问对象与访问对象互相依赖,自然不利于分离变化,必须去掉一层依赖关系。

我们尝试把Visitor对Person(元素)的依赖关系去掉,抽象出对应每个具体元素的ElementVisitor接口 -->ManVisitor,WomanVisitor,然后把Visitor对Person的依赖关系转移到ManVisitor与 WomanVisitor身上。
 
现在Visitor接口已经没有任何抽象方法,只是一个空接口,每一个具体元素对应有一个ElementVisitor接口,每一个元素对应的ElementVisitor接口有访问该元素的visit(),相当把原来在Visitor接口中声明工作,交由各个具体ElementVisitor接口完成。


经过改造后的代码:
原Visitor接口

public interface Visitor {
      //退化到没有任何抽象方法
}



新增加ManVisitor,WomanVisitor接口

public interface ManVisitor {
      public void visit(Man man);
}

public interface WomanVisitor {
      public void visit(Woman w);
}

 
具体Visitor实现类现在同时实现3个接口

//由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口
public class Success implements Visitor,WomanVisitor,ManVisitor{

    public void visit(Man man) {
        System.out.println("当男人成功时,背后多半有一个伟大的女人");
    }

    public void visit(Woman girl) {
        System.out.println("当女人成功时,背后大多有一个不成功的男人");
    }
}


//由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口
public class Love implements Visitor,WomanVisitor,ManVisitor{

    public void visit(Man man) {
        System.out.println("当男人恋爱时,凡事不懂也装懂");
    }

    public void visit(Woman girl) {
        System.out.println("当女人恋爱时,遇事懂也装不懂");
    }
}



Person接口没有变化,依旧只依赖于Visitor接口

public interface Person {
      void accept(Visitor visitor);
}



改造后的具体元素类Man与Woman

public class Man implements Person {

    // 先对visitor进行类型转换,再执行visit方法,因为Visitor接口已经没有声明任何抽象方法了
    public void accept(Visitor visitor) {
        if (visitor instanceof ManVisitor) {
            ManVisitor mv = (ManVisitor) visitor;
            mv.visit(this);
        }
    }
}


public class Woman implements Person {

    // 先对visitor进行类型转换,再执行visit方法,因为Visitor接口已经没有声明任何抽象方法了
    public void accept(Visitor visitor) {
        if (visitor instanceof WomanVisitor) {
            WomanVisitor wv = (WomanVisitor) visitor;
            wv.visit(this);
        }
    }
}



ObjectStructure与客户端测试代码没有变化

import java.util.*;

public class ObjectStructure {
    private List<Person> elements = new ArrayList<Person>();

    public void attach(Person element){
        elements.add(element);
    }
   
    public void detach(Person element){
        elements.remove(elements);
    }
   
    //遍历各种具体元素并执行他们的accept方法
    public void display(Visitor visitor){
        for(Person p:elements){
            p.accept(visitor);
        }
    }
}


public class Client {
      public static void main(String[] args) {
        ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure
        //实例化具体元素
        o.attach(new Man()); 
        o.attach(new Woman());
       
        //当成功时不同元素的不同反映
        Visitor success = new Success();           //依赖于抽象的Visitor接口
        o.display(success);
       
        //当恋爱时的不同反映
        Visitor amativeness = new Love();          //依赖于抽象的Visitor接口
        o.display(amativeness);       
    }
}



至此改造完毕!我们执行客户端测试代码,结果显示:
当男人成功时,背后多半有一个伟大的女人
当女人成功时,背后大多有一个不成功的男人
当男人恋爱时,凡事不懂也装懂
当女人恋爱时,遇事懂也装不懂

此时,客户端仍然只依赖于Visitor空接口与ObjectStructure类。可能一开始大家会认为空接口没有什么用,现在就能体现出他的威力了,使客户端与具体Visitor的高度解耦!也正是这种思维的核心在JavaAPI中也有类似的应用,这种空接口被称为标识接口。比如java.io.Serializable与java.rmi.Remote等,标识接口里没有任何方法和属性,标识不对实现接口不对实现它的类有任何语义上的要求,它仅仅是表明实现它的类属于一种特定的类型。
上面具体访问者实现的多个接口被称为混合类型。这个概念《Java与模式》中有提及过:当一个具体类处于一个类的等级结构之中的时候,为这个具体类定义一个混合类型是可以保证基于这个类型的可插入性的关键。

=================================无敌分界线====================================

讲了这么长,现在我们测试下改造后的访问者模式
首先增加一种行为(状态),即原访问者模式的优点

增加一个具体访问者Fail,修改一下客户端测试代码

public class Fail implements Visitor,ManVisitor,WomanVisitor{

    public void visit(Man man) {
        System.out.println("当男人失败时,闷头喝酒,谁也不用劝");
    }

    public void visit(Woman woman) {
        System.out.println("当女人失败时,眼泪汪汪,谁也劝不了");
    }
}



public class Client {
      public static void main(String[] args) {
        ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure
        //实例化具体元素
        o.attach(new Man()); 
        o.attach(new Woman());
       
        //当成功时不同元素的不同反映
        Visitor success = new Success();           //依赖于抽象的Visitor接口
        o.display(success);
        System.out.println();
       
        //当恋爱时的不同反映
        Visitor amativeness = new Love();          //依赖于抽象的Visitor接口
        o.display(amativeness);       
        System.out.println();
       
        //新增加失败时的不同反映
        Visitor fail = new Fail();
        o.display(fail);
    }
}



结果显示:
当男人成功时,背后多半有一个伟大的女人
当女人成功时,背后大多有一个不成功的男人

当男人恋爱时,凡事不懂也装懂
当女人恋爱时,遇事懂也装不懂

当男人失败时,闷头喝酒,谁也不用劝
当女人失败时,眼泪汪汪,谁也劝不了



增加新的行为(状态)与原来一样方便!只需要增加一个具体访问者即可!
现在我们来增加一个具体元素(正是写这篇文章的初衷)

首先增加一个具体元素Bruce

public class Bruce implements Person{
   
    public void accept(Visitor visitor) {       
        if(visitor instanceof BruceVisitor){
            BruceVisitor bv = (BruceVisitor) visitor;
            bv.visit(this);
        }
        //这个else可写可不写
        else{
            String s = visitor.getClass().getName();
            String state = s.substring(s.lastIndexOf(".")+1,s.length());
            System.out.println("噢..原来怪兽在"+state+"的时候是没有行为的!!");
        }       
    }
}


//按照新的思维方式增加一个对应的ElementVisitor接口
public interface BruceVisitor {
      public void visit(Bruce bruce);
}



我们让Success这个具体访问者多实现一个BruceVisitor访问者接口,和修改一下客户端代码进行测试

public class Success implements Visitor,WomanVisitor,ManVisitor,BruceVisitor{

    public void visit(Man man) {
        System.out.println("当男人成功时,背后多半有一个伟大的女人");
    }

    public void visit(Woman girl) {
        System.out.println("当女人成功时,背后大多有一个不成功的男人");
    }

    public void visit(Bruce bruce) {
        System.out.println("当怪兽成功时.........无语..........");
    }
}


public class Client {
      public static void main(String[] args) {
        ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure

        o.attach(new Man()); 
        o.attach(new Woman());
        o.attach(new Bruce());      //新增一种具体元素Bruce
       
        Visitor success = new Success();           //依赖于抽象的Visitor接口
        o.display(success);
        System.out.println();
       
        Visitor amativeness = new Love();          //依赖于抽象的Visitor接口
        o.display(amativeness);       
        System.out.println();
       
        Visitor fail = new Fail();
        o.display(fail);
    }
}



显示结果:
当男人成功时,背后多半有一个伟大的女人
当女人成功时,背后大多有一个不成功的男人
当怪兽成功时.........无语..........

当男人恋爱时,凡事不懂也装懂
当女人恋爱时,遇事懂也装不懂
噢..原来怪兽在Love的时候是没有行为的!!

当男人失败时,闷头喝酒,谁也不用劝
当女人失败时,眼泪汪汪,谁也劝不了
噢..原来怪兽在Fail的时候是没有行为的!!


这个结果你满意吗?
虽然,这只是部分符合“开放-封闭”原则,我们不需要修改Visitor接口,但还是得去修改Success实现新的接口。但是修改具体类比修改接口的代价小得多,不需要重新编译所有访问接口和具体访问者。使我们面对新的变化也容易得多。而且这还有一个好处,就是可以让各种元素有选择地让别人访问,如上述例子,这样使访问者模式的运用起来更加灵活。
posted @ 2010-10-31 17:24 Eric_jiang 阅读(379) | 评论 (0)编辑 收藏

类适配器
客户的开发人员定义了一个接口,期望用这个接口来完成整数的求和操作,接口定义如下:
 
public interface Operation{   
      public int add(int a,int b);   

 开发人员在了解这个接口的定义后,发现一个第三方类,里面有一个方法能实现他们期望的功能,其代码如下:
 
public class OtherOperation{   
      public int otherAdd(int a,int b){   
           return a + b;   
      }   

 以上第三方类OtherOperation的方法public int otherAdd(int a,int b)所提供的功能,完全能符合客户的期望,所以只需要想办法把OtherOperation的otherAdd(int a,int b)和客户的Operation接口联系起来,让这个第三方类来为客户提供他们期望的服务就行了,这样就避免了开发人员再度去研究类似OtherOperation的otherAdd(int a,int b)方法的实现(利用已有的轮子,避免重复发明),这方法之一,就是用适配器模式:
 
public class AdapterOperation extends OtherOperation implements Operation{   
      public int add(int a,int b){   
           return otherAdd(a,b);   
      }   

 以上就是适配器的实现方法之一,类适配器,在以上实现中存在着三中角色分别是:
1:适配目标角色:Operation。
2:适配类(原)角色:OtherOperation。
3:适配器角色:AdapterOperation。
其中适配器角色是适配器模式的核心。
适配器的主要工作就是通过封装现有的功能,使他满足需要的接口。
对象适配器
我们再来看看另一种情况:
假如客户接口期望的功能不止一个,而是多个:
 
public interface Operation{   
      public int add(int a,int b);   
      public int minus(int a,int b);   
      public int multiplied(int a,int b);   

 而能提供这些实现的原可能不止一个:
 
public class OtherAdd{   
      public int otherAdd(int a,int b){   
           return a + b;   
      }   
}   
  
public class OtherMinus{   
      public int minus(int a,int b){   
           return a - b;   
      }   
}   
  
public class OtherMultiplied{   
      public int multiplied(int a,int b){   
           return a * b;   
      }   

 由于java是不能实现多继承的,所以我们不能通过构建一个适配器,让他来继承所有原以完成我们的期望,这时候怎么办呢?只能用适配器的另一种实现--对象适配器:
 
public class AdapterOperation implements Operation{   
      private OtherAdd add;   
      private OtherMinus minus;   
      private OtherMultiplied multiplied;   
  
      public void setAdd(OtherAdd add){   
            this.add = add;   
      }   
  
      public void setMinus(OtherMinus minus){   
            this.minus = minus;   
      }   
  
      public void setMultiplied(OtherMultiplied multiplied){   
            this.multiplied = multiplied;   
      }   
  
      //适配加法运算   
      public int add(int a,int b){   
           return add.otherAdd(a,b);   
      }   
  
      //适配减法运算   
      public int minus(int a,int b){   
          return minus.minus(a,b);   
      }   
  
      //适配乘法运算   
      public int multiplied(int a,int b){   
         return multiplied.multiplied(a,b);   
      }   
}
 
 

上面代码很明显,适配器并不是通过继承来获取适配类(原)的功能的,而是通过适配类的对象来获取的,这就解决了java不能多继承所带来的不便了。这也是java提倡的编程思想之一,即尽量使用聚合不要使用继承。 还有一种情况是需要使用对象适配器的。我们来看看,单我们的客户提供的需求并不是一个明确的接口,而是一个类,并没有定义期望的方法,如下
 
public class A{   
   public int add(int a,int b){   
      return a + b;   
   }   

 
现在客户要一个新类B,要求能在保留类A功能的情况下增加一个运算减法的功能,并要求B能随时替换掉A但不能对已有系统造成影响。这样我们只能新建一个类B,并让B继承A。
 
public class B extends A{   
    b(){   
      super();   
    }   
  
    public int minus(int a,int b){   
           //待实现的减法运算函数..   
    }   

 
这时候,我们发现类C已经提供了实现减法的函数,
 
public class C{
    public int minus(int a,int b){
           return a - b;
    }
}

为了避免重复去设计该函数,我们决定引入C类,通过适配C类来达到我们的期望,但问题是A和C都是一个具体类,我们无法让B同时继承这个两个类,而B继承A又是必须的,所以我们只能考虑把C给内聚到B内部,对象适配器又得派上用场了。
 
public class B extends A{
    private C c;
    B(){
      super();
    }
    public void setMinus(C c){
         this.c= c;
    }
    public int minus(int a,int b){
           return c.minus(a,b);
    }
}

这样,在需要A类的地方都能用B类来代替,同时又保证了新的功能的引入。
更灵活的实现--隐藏目标接口的抽象适配器
做java 桌面应用的都知道WindowListener接口,
 
public interface WindowListener extends EventListener{
 public void windowActivated(WindowEvent e);
 public void windowClosed(WindowEvent e);
 public void windowClosing(WindowEvent e);
 public void windowDeactivated(WindowEvent e);
 public void windowDeiconified(WindowEvent e);
 public void windowIconified(WindowEvent e);
 public void windowOpened(WindowEvent e);
}

要实现这个接口,我们就必须实现它所定义的所有方法,但是实际上,我们很少需要同时用到所有的方法,我们要的只是其中的两三个。为了不使我们实现多余的方法,
jdk WindowListener提供了一个WindowListener的默认实现类WindowAdapter类,这是一个抽象类,
 
public abstract class WindowAdapter implements WindowListener{
 public void windowActivated(WindowEvent e){}
 public void windowClosed(WindowEvent e){}
 public void windowClosing(WindowEvent e){}
 public void windowDeactivated(WindowEvent e){}
 public void windowDeiconified(WindowEvent e){}
 public void windowIconified(WindowEvent e){}
 public void windowOpened(WindowEvent e){}
}

WindowAdapter类对WindowListener接口的所有有方法都提供了空实现,
有了WindowAdapter类,我们只需要去继承WindowAdapter,然后选择我们所关心的方法来实现就行了,这样就避免了直接去实现WindowListener接口。

posted @ 2010-10-29 20:56 Eric_jiang 阅读(303) | 评论 (0)编辑 收藏

核心:要使window.close在Firefox中有效,必须先设置window.open

对于最常用的关闭窗口链接,都比较熟悉,使用的Javascript函数就是:window.close(),写完后在IE下测试,完全搞定;当你用Mozilla内核的浏览器打开时,点击关闭窗口按钮,你会发现事件并不会像你想象的那么顺利,窗口根本就是无动于衷(真痛恨浏览器的兼容性吧,哈哈,淡定,没有浏览器的兼容性,又怎么会有前端开发这个职业呢),这并不是Mozilla内核浏览器不支持window.close()这个方法(打开W3CSCHOOL,你会发现在Firefox 1.0就已经支持了),那到底是什么原因引起Firefox没有执行这段代码呢(准确地说应该是执行了,但没有产生预期的效果而已,本人一直坚信:就目前这技术,机器是不会骗人的,一切还是人为原因)?

经过Google一翻,在一篇名为:在Firefox 2.0中无法用Javascript关闭父窗口(原名:Cannot close parent window using javascript in Firefox 2.0)中找到真正的原因,其中有个网友直接使用下面的代码的(问题是:Firefox 2.0以下执行,但2.0无效):

function closeWindow() {
window.open('','_parent','');
window.close();
}

一位很了解这个问题的网友给出讲解并贴出了原因:它当然不会关闭,如果在window.open方法中不添加URL参数照样执行,但是下面的一行并不会执行或不会做任何事情。下面的稍微变化的代码指出的close()方法常见的错误―close()方法不能关闭非Javascript脚本打开的窗口(原文:Yes, that doesn’t do anything. If I change the missing URL in the window.open command to an actual page, it executes but then the next line doesn’t run or doesn’t do anything. The following variation gives the usual script error for the close() method in this scenario — can’t close a window not opened by a script):

function closeWindow() {
newwin = window.open(location.href,'_parent','');
newwin.close();
}

如果你使用window.open打开一个窗口,这时你才可以使用window.close去关闭它,相反如果你通过常规链接打开的窗口,window.close根本就关闭不了它,需要额外的用户权限;这比直接使用关闭按钮更令人讨厌…(原文:If you launch the initial Firefox window using window.open, then window.close should work on it. However, if it is launched from a regular URL, then as you know it doesn’t work. There is a way to ask the user for extra permissions. However, that might be more annoying than leaving the window open…),原来上面的两段代码都只针对使用window.open打开的窗口,才能执行window.close关闭,而对于URL链接新开的窗口,必须要额外的用户权限(UniversalBrowserWrite privilege),其实只要在执行关闭窗口之前加上:

netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");

这段代码即可,具体说明参见Mozilla官网的“如何使用扩展权限”(Using Expanded Privileges)

posted @ 2010-10-19 13:08 Eric_jiang 阅读(2852) | 评论 (0)编辑 收藏

仅列出标题
共57页: First 上一页 41 42 43 44 45 46 47 48 49 下一页 Last