关于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();

         }

     }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java中的抽象工厂模式是一种创建型设计模式,它可以将一组相关的产品集合起来,并且创建整个产品家族。与工厂方法模式不同的是,抽象工厂模式有多个抽象产品类,每个抽象产品类都有对应的具体产品类。抽象工厂模式中声明了多个工厂方法,用于创建不同类型的产品。抽象工厂可以是接口、抽象类或者具体类。 在Java中实现抽象工厂模式时,我们需要定义抽象工厂接口或抽象类,其中包含多个工厂方法,用于创建不同类型的产品。具体工厂类需要实现抽象工厂接口或继承抽象工厂类,并实现工厂方法。具体产品类需要实现相应的抽象产品类。客户端调用时可以通过抽象工厂对象获取不同类型的产品实例。 使用抽象工厂模式的优点是可以将一组相关的产品集合起来,并且创建整个产品家族的模式。这样可以提供更高层次的抽象和灵活性,使得系统更易于扩展和维护。但是抽象工厂模式也有一些缺点,例如增加新的产品族会比较麻烦,需要修改抽象工厂接口或抽象工厂类以及所有的具体工厂类。抽象工厂模式适用于需要创建一系列相关或相互依赖的对象的场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [java设计模式【抽象工厂模式】](https://blog.csdn.net/qq_42872720/article/details/130724519)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [java设计模式-抽象工厂类详解](https://blog.csdn.net/qq_48642405/article/details/122062202)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值