HelloWorld 善战者,求之于势,不责于人;故能择人而任势。

知止而后有定,定而后能静,静而后能安,安而后能虑,虑而后能得。物有本末,事有终始。知所先后,则近道矣。

  BlogJava :: 首页 ::  :: 联系 ::  :: 管理 ::
  167 随笔 :: 1 文章 :: 40 评论 :: 0 Trackbacks

以下为java抽象工厂模式的一个例子,都是个人的一点想法,有什么不足的地方,恳求大家予以指出,欢迎讨论

我们使用的界面上有

文本 {Linux文本,Windows文本}

标签 {Linux标签,Windows标签}

等等.

第一部分 抽象工厂的实现

interface 文本 {}

interface 标签 {}

class Linux文本 implements 文本{

     public String toString() {

         return "Linux文本";

     }

}

class Linux标签 implements 标签{

     public String toString() {

         return "Linux标签";

     }

}

class Windows文本 implements 文本{

     public String toString() {

         return "Windows文本";

     }

}

class Windows标签 implements 标签{

     public String toString() {

         return "Windows标签";

     }

}

interface 组件工厂 {

     public 文本 生产文本组件();

     public 标签 生产标签组件();

}

class Linux组件工厂 implements 组件工厂 {    

     public 文本 生产文本组件() {

         return new Linux文本();

     }

     public 标签 生产标签组件() {

         return new Linux标签();

     }

   

}

class Windows标签组件工厂 implements 组件工厂 {    

     public 文本 生产文本组件() {

         return new Windows文本();

     }

     public 标签 生产标签组件() {

         return new Windows标签();

     }

   

}

class 客户系统显示 {

     private 文本 text;

     private 标签 label;

     public static void main(String args[]) {

         客户系统显示 clientOS = new 客户系统显示();

         组件工厂 factory = new Linux组件工厂();

         clientOS.label = factory.生产标签组件();

         clientOS.text = factory.生产文本组件();    

         System.out.println(clientOS.label);

         System.out.println(clientOS.text);

     }

}

如果按照上面的标准,我们要添加一个新的组件 下拉框

A.需要修改的地方有

1.组件工厂

2.Linux组件工厂

3.Windows标签组件工厂

B.需要增加的有

1.interface 下拉框 {}

2.class Linux下拉框 implements 下拉框

3.class Windows下拉框 implements 下拉框

C.调用的地方也会多出一个factory.生产下拉框组件();    

第二部分 改革抽象工厂

有没有觉得要改动的地方有点多呢,下面我们来改革一下

1.把 组件工厂中的

生产文本组件();

生产标签组件();

...

都改为

生产组件(组件标识);

这样带来的好处就是前面提到的,以下的修改就免去了

/**************************/

......

A.需要修改的地方有

1.组件工厂

2.Linux组件工厂

3.Windows标签组件工厂

......

/**************************/

要做到上面的,需要做以下几件事情

1.增加一个Annotation来说明后面增加的 组件注册表

@interface 组件描述 {

     Class 组件类();

   

}

2.增加一个Enum

enum 组件注册表 {

     /**

      * Linux_文本 的对应实体类为 Linux文本

      */

     @组件描述(组件类 = Linux文本.class)

     Linux_文本,

   

     @组件描述(组件类 = Linux标签.class)

     Linux_标签,

   

     @组件描述(组件类 = Windows文本.class)

     Windows_文本,

   

     @组件描述(组件类 = Windows标签.class)

     Windows_标签,

}

3.我们不再需要

interface 组件工厂,class Windows标签组件工厂,class Linux组件工厂

我们把 接口 组件工厂改为实体类

为了保持可以扩展和维护

我们定义了一个 接口 工厂

interface 工厂 {

}

class 组件工厂 implements 工厂 {

     public 组件 生产组件(组件注册表 ID) throws Exception {

         try {

             Field f = 组件注册表.class.getField(ID.toString());

             组件描述 描述 = f.getAnnotation(组件描述.class);

             Class 组件类 = 描述.组件类();

             return (组件) 组件类.newInstance();

             // 注意,组件类.newInstance();的调用的时候要确保这个组件类有个不带参数的构造函数

             // 如果要使用带参数的构造函数,可以在@interface 组件描述 中增加一个成员

             // 构造函数[] 构造函数参数() default{};

             // @interface 构造函数 {Class[] 构造函数的参数();}

             // 通过 组件类.getConstructors(); 来得到这个类的不同构造方法

             // 这样就可以根据用户提供的信息用不同的构造函数实例话对象

             // 带不同的构造函数,这里先不讨论,后面我会给出代码

         } catch (Exception e) {

             throw new Exception ("没有找到对应的组件");

         }

     }

}

经过上面的修改,代码如下

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.reflect.Field;

@Retention(RetentionPolicy.RUNTIME)

@interface 组件描述 {

     Class 组件类();

   

}

enum 组件注册表 {

     @组件描述(组件类 = Linux文本.class)

     Linux_文本,

   

     @组件描述(组件类 = Linux标签.class)

     Linux_标签,

   

     @组件描述(组件类 = Windows文本.class)

     Windows_文本,

   

     @组件描述(组件类 = Windows标签.class)

     Windows_标签,

}

interface 组件 {}

interface 文本 extends 组件 {}

interface 标签 extends 组件 {}

class Linux文本 implements 文本{

     public String toString() {

         return "Linux文本";

     }

}

class Linux标签 implements 标签{

     public String toString() {

         return "Linux标签";

     }

}

class Windows文本 implements 文本{

     public String toString() {

         return "Windows文本";

     }

}

class Windows标签 implements 标签{

     public String toString() {

         return "Windows标签";

     }

}

interface 工厂 {}

class 组件工厂 implements 工厂{

     public 组件 生产组件(组件注册表 ID) throws Exception {

         try {

             Field f = 组件注册表.class.getField(ID.toString());

             组件描述 描述 = f.getAnnotation(组件描述.class);

             Class 组件类 = 描述.组件类();

             return (组件) 组件类.newInstance();

         } catch (Exception e) {

             throw new Exception ("没有找到对应的组件");

         }

     }

}

class 客户系统显示 {

     private 文本 text;

     private 标签 label;

     public static void main(String args[]) {

         客户系统显示 clientOS = new 客户系统显示();

         组件工厂 factory = new 组件工厂();

         try {

             clientOS.text = (文本) factory.生产组件(组件注册表.Linux_文本);

             clientOS.label = (标签) factory.生产组件(组件注册表.Linux_标签);

         } catch (Exception e) {

             e.printStackTrace();

         }

         System.out.println(clientOS.label);

         System.out.println(clientOS.text);

     }

}

这个时候我们增加一个 下拉框

需要改动的地方

1.增加一个 interface 下拉框 extends 组件 {}

2.增加2个实现类

class Windows下拉框 implements 下拉框{}

class Linux下拉框implements 下拉框{}

3.组件注册表 增加2个成员

@组件描述(组件类 = Linux下拉框.class)

Linux_下拉框,    

@组件描述(组件类 = Windows下拉框.class)

Windows_下拉框,

和上面的比起来我们只需要在 组件注册表中增加2个成员,而不需要去修改

1.组件工厂

2.Linux组件工厂

3.Windows标签组件工厂

因为这里要修改3个地方,是不是觉得麻烦,反正我觉得麻烦了点

还有一点就是用户调用的时候不需要再使用factory.生产标签组件();等方法,只要一个factory.生产组件就可以了,这样符合简单工厂的模式

第三部分 带参数的构造函数代码

import java.lang.annotation.Annotation;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.util.ArrayList;

import java.util.List;

@Retention(RetentionPolicy.RUNTIME)

@interface 构造函数 {

     /**

      * 构造函数的参数类型

      * @return

      */

     Class[] 构造函数的参数();

}

@Retention(RetentionPolicy.RUNTIME)

@interface 组件描述 {

     Class 组件类();

   

     /**

      * 返回组件的构造函数 <br>

      * 如果长度为0,则调用没有参数的构造函数 <br>

      * @return 构造函数[]

      */

     构造函数[] 构造函数参数() default{};

   

}

enum 组件注册表 {

     /**

      * Linux_文本 的对应实体类为 Linux文本 <br>

      * Linux的构造函数有 <br>

      * 1. Linux文本(String 显示的文字) ; <br>

      * 2. Linux文本(String 显示的文字, Integer 文本字体大小);

      */

     @组件描述(组件类 = Linux文本.class,

             构造函数参数 = {@构造函数(构造函数的参数={String.class}) ,

         @构造函数(构造函数的参数={String.class, Integer.class}) } )

     Linux_文本,

   

     @组件描述(组件类 = Linux标签.class)

     Linux_标签,

   

     @组件描述(组件类 = Windows文本.class)

     Windows_文本,

   

     @组件描述(组件类 = Windows标签.class)

     Windows_标签,

}

interface 组件 {}

interface 文本 extends 组件 {}

interface 标签 extends 组件 {}

class Linux文本 implements 文本{

     private String text;

     private Integer size;

     public Linux文本(String text) {

         this.text = text;

     }

     public Linux文本(String text, Integer size) {

         this.text = text;

         this.size = size;

     }

     public String toString() {

         return "Linux文本" + (text == null ? "":",文本内容为:"+text) + (size == null ? "":",文本字体大小为:"+size);

     }

}

class Linux标签 implements 标签{

     public String toString() {

         return "Linux标签";

     }

}

class Windows文本 implements 文本{

     public String toString() {

         return "Windows文本";

     }

}

class Windows标签 implements 标签{

     public String toString() {

         return "Windows标签";

     }

}

interface 工厂 {}

class 组件工厂 implements 工厂{

     public 组件 生产组件(组件注册表 ID, Object[] 参数) throws Exception {

         try {

             Field f = 组件注册表.class.getField(ID.toString());

             组件描述 描述 = f.getAnnotation(组件描述.class);

             Class 组件类 = 描述.组件类();

             构造函数[] ano = 描述.构造函数参数();

             if (参数 != null) {

                 for (int i = 0; i < ano.length; i++) {

                     构造函数 temp = ano;

                     Class[] 构造函数S = temp.构造函数的参数();                    

                     if (参数.length == 构造函数S.length) {

                         for (int j = 0; j < 参数.length; j++) {

                             if (参数[j].getClass().toString().equals(构造函数S[j].toString())) {

                                 if ( j == 参数.length - 1) {

                                     Constructor cons = 组件类.getConstructor(构造函数S);

                                     return (组件) cons.newInstance(参数);

                                 }

                             } else break;

                         }

                     }

                     continue;

                 }

                 throw new Exception ("没有找到对应的组件");

             } else

                 return (组件) 组件类.newInstance();

         } catch (Exception e) {

             e.printStackTrace();

             throw new Exception ("没有找到对应的组件");

         }

     }

}

class 客户系统显示 {

     private 文本 text;

     private 标签 label;

     public static void main(String args[]) {

         客户系统显示 clientOS = new 客户系统显示();

         组件工厂 factory = new 组件工厂();

         try {

             Object [] params = {"初始化文本", new Integer(20)};

             clientOS.text = (文本) factory.生产组件(组件注册表.Linux_文本,params);

             clientOS.label = (标签) factory.生产组件(组件注册表.Linux_标签,null);

             System.out.println(clientOS.label);

             System.out.println(clientOS.text);

             Object [] params2 = {"初始化"};

             clientOS.text = (文本) factory.生产组件(组件注册表.Linux_文本,params2);

             System.out.println(clientOS.text);

         } catch (Exception e) {

             e.printStackTrace();

         }

     }

}



</script>

posted on 2007-08-13 18:57 helloworld2008 阅读(705) 评论(0)  编辑  收藏 所属分类: java - 模式

只有注册用户登录后才能发表评论。


网站导航: