工厂模式和“万能”工厂类

字节逐风鹤
• 阅读 4373

需要构造一个类的对象,我们通常会用new的方法来构造:

A a = new A();

但是如果随着这个对象被创建的同时还必须进行其他相对复杂的操作,那么在新建构造一个对象代码就显得非常复杂,这个复杂的代码通常还需要每一次都复写,大大增加了冗余。

因此我们构造了生产这个类对应对象的工厂,用工厂的方法来生产对象。
比如:我们需要在构造一个对象时并不知道这个对象中的某个字段的确切值,该值保存在配置文件中,所以每次构造对象都要进行配置文件的读取,依据配置文件中的内容来确定这个对象中该字段的信息,这个过程如果直接使用new来实现将会造成大量代码的冗余,大量冗余存在于配置文件的加载和读取,不妨把它封装成工厂类,在工厂类内部实现配置文件的加载和读取。

有如下配置文件:/src/config.properties:

ImportantString = OK

有如下预创建的对象所属类:/src/A.java:

public class A {
    private String Aname;
    public void Ashout(){
        System.out.println("I am "+Aname+",hahaha !");
    }
    public String getAname() {
        return Aname;
    }
    public void setAname(String aname) {
        Aname = aname;
    }
}

有如下测试文件:/src/Test.java:

public class Test{
    public static void main(String[] args) {
        A a = AFactory.getA();
        a.Ashout();
    }
}

则可以构造工厂类来生产该类的对象,生产过程中加载读取配置文件并将配置文件中的重要字段赋值给创建出的对象,并返回这个创建出的对象。

如下工厂类文件:/src/AFactory.java:

public class AFactory {
    private static Properties properties = null;
    private static String ANameToGet;
    private AFactory() {

    }
    static{
        try {
            properties = new Properties();
            properties.load(new FileReader(AFactory.class.getClassLoader().getResource("config.properties").getPath()));
            ANameToGet = properties.getProperty("ImportantString");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public static A getA(){
        A a = new A();
        a.setAname(ANameToGet);
        return a;
    }
}

我们可以发现,通过工厂类的包装,在调用工厂类方法构造对象时可以十分轻松地完成任务,而后面的其他任务则交由工厂类的静态代码块完成。

那么什么是万能工厂类呢?万能当然不是指能完成一切的工厂,而是说在很多情况下,我们可能需要构造各种类的对象,而这些对象在构造过程中可能也会完成很多跟构造相分离的相对复杂的任务,这些任务可能会导致前台代码冗余,而恰恰我们要构造的这些对象虽然分属不同的类却有结构相同的代码,这是我们不妨使用泛型来进一步解决这个问题。

以上面的例子为基础,我们需要两个类,在这两个类的对象的创建过程中都必须要检查配置文件中的一对Key是否相等,相等的Key才能允许对象的创建,
否则不允许创建,这个过程中如果在new之前直接做判断逻辑,将会导致大量的代码冗余,因为每个类的对象创建前都要进行相同的判断。因此我们考虑
把这部分代码写入工厂类,再生产过程前进行判断,过程封装进工厂类。
但是由于我们两个类的对象的生成实现过程类似,因此不需要分别写工厂,而是统一地写一个泛型化的工厂,依据传进的类的类型利用Class.forName(className).newInstance()来创建新的对象。

有如下配置文件:/src/config.properties:

Key1 = RightKey
Key2 = RightKey

有如下预创建的对象所属类:/src/A.java:

public class A {
}

/src/B.java:

public class B {
}

有如下测试文件:/src/Test.java:

public class Test{
    public static void main(String[] args) {
        A a = CommonFactory.getInstance();
        B b = CommonFactory.getInstance();
    }
}

则可以构造工厂类来生产该类的对象,生产过程中加载读取配置文件并将判断配置文件中的Key以确定对象是否能正常生成,如果可以返回这个创建出的对象。

如下工厂类文件:/src/CommonFactory.java:

public class CommonFactory {
    private static Properties properties = null;
    private static String Key1;
    private static String Key2;
    static boolean no;
    private CommonFactory() {
    }
    static{
        try {
            properties = new Properties();
            properties.load(new FileReader(CommonFactory.class.getClassLoader().getResource("config.properties").getPath()));
            Key1 = properties.getProperty("Key1");
            Key2 = properties.getProperty("Key2");
            no = Key1.equals(Key2);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    public static <T> T getInstance(Class<T> clazz){
        try {
            String className = clazz.getName();
            if(no){
                T t = (T) Class.forName(className).newInstance();
                System.out.println(className+" Object Astablished Successfully");
                return t;
            }
            else
            {
                System.out.println(className+" Object Astablished failed");
                return null;
            }


        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }
}
点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
java中的23种设计模式
java中一共23种设计模式!按照目的来分,设计模式可以分为创建型模式、结构型模式和行为型模式。创建型模式用来处理对象的创建过程;结构型模式用来处理类或者对象的组合;行为型模式用来对类或对象怎样交互和怎样分配职责进行描述。创建型模式用来处理对象的创建过程,主要包含以下5种设计模式:工厂方法模
Stella981 Stella981
3年前
Exceptionless
<divid"cnblogs\_post\_body"class"blogpostbodycnblogsmarkdown"<h1id"exceptionless.netcore开源日志框架"Exceptionless.NetCore开源日志框架</h1<blockquote<p作者:markjiang7m2<b
Wesley13 Wesley13
3年前
C#简单工厂模式
C简单工厂模式模型,建立一个模型,构建我们的实际工程,项目。​所有面向对象的编程都是在我们生活中存在的,从词义的解释就是我们生活中的工厂就是负责生产产品的,而到开发中对应的就是NEW不同的对象,该模式主要解决的问题就是解决创建对象与该类的解耦。设计原则中经常说的类单一职责、封装性都有体现。编程中的简单工厂就是一个生产
Wesley13 Wesley13
3年前
Java描述设计模式(04):抽象工厂模式
一、抽象工厂模式1、生活场景汽车生产根据用户选择的汽车类型,指定不同的工厂进行生产,选择红旗轿车,就要使用中国工厂,选择奥迪轿车,就要使用德国工厂。2、抽象工厂模式1.抽象工厂模式:定义了一个interface用于创建相关对象或相互依赖的对象,而无需指明具体的类;2.抽象工厂模式可以
Wesley13 Wesley13
3年前
PHP算法之判断是否是质数
<h3质数的定义</h3<blockquote质数又称素数。一个大于1的自然数,除了1和它自身外,不能整除其他自然数的数叫做质数;否则称为合数。</blockquote<h3实现思路</h3<p循环所有可能的备选数字,然后和中间数以下且大于等于2的整数进行整除比较,如果能够被整数,则肯定不是质数,相反,就是质数。</p<h3第一种算
Stella981 Stella981
3年前
Python之设计模式
一、设计模式分类a、创建型模式简单工厂模式一、内容不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。二、角色工厂角色(Creator)抽象产品角色(Product)具体产品角色(ConcreteProduct)
Wesley13 Wesley13
3年前
4种常见的 PHP 设计模式
工厂模式在大型系统中,许多代码依赖于少数几个关键类。需要更改这些类时,可能会出现困难。例如,假设您有一个从文件读取的 User 类。您希望将其更改为从数据库读取的其他类,但是,所有的代码都引用从文件读取的原始类。这时候,使用工厂模式会很方便。_工厂模式_ 是一种类,它具有为您创建对象的某些方法。您可以使用工厂类创建对象,而不直接使用 
Wesley13 Wesley13
3年前
23种设计模式(面向对象语言)
一、设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其他关联对象的创建、组合和表示方式。所有的创建型模式都有两个主要功能:  1.将系统所使用的具体类的信息封装起来  2.隐藏
Wesley13 Wesley13
3年前
JS创建对象模式7种方法详解
创建对象的几种模式虽然Object构造函数或者字面量,都可以用来创建对象,但这些方式有明显的缺点:使用同一个接口创建很多对象,会产生大量的代码,于是,工厂模式诞生了1工厂模式工厂模式是广为人知的设计模式,抽象了创建具体对象的过程。在ES6的Class创建类之前,是无法创建类的,开发人员就发明了一种函数,用函数来封
Wesley13 Wesley13
3年前
C++ 常用设计模式(学习笔记)
设计模式1、工厂模式在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式作为一种创建模式,一般在创建复杂对象时,考虑使用;在创建简单对象时,建议直接new完成一个实例对象的创建。1.1、简单工厂模式主要特点是需要在工厂类中做判断,从而创造相应的产品,当