设计模式,2/23,工厂模式

博客园太难用了,第二页居然连摘要都显示不出来了,选列出标题也没用,选列出摘要也没用。

而且都说第一页全部显示了居然还是只显示摘要,怎么让所有博文都不折叠,在列表里就全显示出来……

还是顾名思义,用一个工厂类来生产对象。

我一开始以为传入的参数是对象,还心想传入对象输出对象这不是有病么,后来发现参数是个类。

 1 public class ProductFactory {
 2     private static Product product = null;
 3     
 4     @SuppressWarnings("unchecked")
 5     public <T extends Product> T createProduct(Class<T> c) {
 6         try {
 7             product = (Product) Class.forName(c.getName()).newInstance();
 8         } catch (Exception e) {
 9             e.printStackTrace();
10         }
11         
12         return (T) product;
13     }
14 }
Product可以替换成任意产品名

为了避免看不懂。

Product接口是这个样子的。

public interface Product {
    public void printName();
}

不管怎么样,先测试一下:

 1 public class Test {
 2     public static void main(String[] args) {
 3         ProductFactory factory = new ProductFactory();
 4         
 5         Product one = factory.createProduct(Product1.class);
 6         one.printName();
 7         System.out.println(one instanceof Product1);
 8         Product two = factory.createProduct(Product2.class);
 9         two.printName();
10     }
11 }
测试类

输出结果:

I am testFactory.Product1
true
I am testFactory.Product2

测试完毕,输出都正常,第二句输出还证明了返回的对象确实是Product1类型的,说明工厂类确实能满足需要。

解释下工厂类。

类中包含一个属性,预先定义了要输出的对象。

然后类中有一个方法,用来产生产品对象,具体的过程是传入一个类,然后用Class类的newInstance()方法来产生一个实例并将其返回。

forName()方法的作用是输入类名返回class对象,但是介于我们传入工厂方法的参数它就是一个class对象,所以总感觉这一步有点多余。

……总之禅里是这么写的,我就照搬了。

…………我改了去测试一下……

……测试完成。

直接这样

product = (Product) c.newInstance();

就可以了,不用forName()也成。

newInstance()方法会抛两个异常,不过用IDE的话反正会有异常提示的,就不说了。

再一个,这段代码里用到了泛型,对的这个用法也是照搬的……不过我保证这些代码都是我回忆着敲的没有对着书抄……

以下内容是自己推测的不保证对。

<T extends Product>一句定义了泛型的类型,然后用在返回类型和输入参数类型里,保证了传入和输出的一定是Product,因为这个工厂根本也不处理别的类型。

往服装厂里传入一块粘土说我要红砖不太对不是。

最后的返回结果直接是product是不行的,因为方法头里定义了返回类型是T,尽管返回值就是Product类型,于是要加上强制转换。

但是强制转换之后eclipse报警告了,跟我说返回之前你得检查一下返回值是不是T。万一是个P呢?

然后我百度谷歌了一下,大家纷纷表示它就是这样的改不了SUN罪大恶极搞到百姓怨声载道而且warning不算错误要不你就屏蔽掉吧。

我心想这怎么行,一个严谨的程序员怎么能看着一个大大的黄色三角裤不没有裤摆在眼前而无动于衷呢。

于是我就试了一下:

if (product instanceof T) {
    return (T) product;
}

结果报了另一种错误,表示泛型是不能用instanceof的,因为在运行时,T的类型信息是被擦除了的。

于是我抱着试试看的心态又去stackoverflow搜了几个相关问题的回答。

然后我决定不整这些没用的。

方法前加上

@SuppressWarnings("unchecked")

搞定。

工厂模式的适用于需要产生多个产品对象的场合,用了就知道。

比如我还想加上一个Product3,我只要写好实现类,然后在场景类里生产它就可以了,绝对低耦合,用户需要知道的只有类名,轻松自如,如鱼得水。

原文地址:https://www.cnblogs.com/chihane/p/3603722.html