ITPub博客

首页 > 应用开发 > Java > 别再到处 new 对象了,试试 3 大工厂模式,真香!!

别再到处 new 对象了,试试 3 大工厂模式,真香!!

Java 作者:喝水会长肉 时间:2021-12-04 16:46:29 0 删除 编辑

你还在到处 new 对象吗?

单身狗:我没对象,new 怎么了?

new 对象本身是没问题的,但也不能全部 new 关键字走天下,其实有更好的方式,合适的时候可以试试工厂模式,代码会更优雅。

什么是工厂模式?

顾名思义,工厂模式中的 "工厂" 指的是创建对象的工厂,它提供了一种创建对象的最佳方式,也就是工厂模式。

工厂模式的好处是这些对象不需要暴露自身的创建过程,统一由工厂模式进行创建和提供,隐藏了创建细节,避免了错误的创建对象的形式,也减少了重复创建冗余代码。

一般情况下,工厂模式可以细分为三类:

  • 简单工厂模式

  • 工厂方法模式

  • 抽象工厂模式

    不过在设计模式权威书籍《 设计模式:可复用面向对象软件的基础》一书中,简单工厂模式只是工厂方法模式的一个特例而已。

所以,从权威的角度说,工厂模式只分为: 工厂模式 和  抽象工厂模式 两大类。

但不管白猫黑猫,能抓老鼠的就是好猫,设计模式亦是如此,不管怎么分类,这些模式都是程序员们历年过往经验的浓缩,都是值得学习和借鉴的。

所以,本文栈长从细分的角度带大家来实战下这三个工厂设计模式。

1、简单工厂

比如 XX 公司是做支付的,公司有几大类的客户:电商商户、银行客户、代理商……

创建这些客户的时候我们可以用简单工厂模式来实现看看。

新建客户基类:

可以把所有客户公共的信息放到一个客户基类中,比如:客户名、客户类型等,所有的客户继承这个抽象基类。


/**

* 客户
*/

@Data
@NoArgsConstructor
@AllArgsConstructor
public abstract class Customer {

    /**
    * 客户名称
    */

    private String name ;

    /**
    * 客户类型
    */

    private String type ;

}


新建电商商户类:


/**

* 商户
*/

@Data
@ ToString (callSuper = true )
public class Merchant extends Customer {

    /**
    * 合同类型
    */

    private int contractType ;

    /**
    * 结算周期(天)
    */

    private int settmentDays ;

    public Merchant ( String name , String type ) {
        super (name , type ) ;
    }
}


新建银行客户类:


/**

* 银行客户
*/

@Data
@ ToString (callSuper = true )
public class BankPartner extends Customer {

    /**
    * 银行编码
    */

    private String code ;

    /**
    * 银行地址
    */

    private String address ;

    public BankPartner ( String name , String type ) {
        super (name , type ) ;
    }
}


新建代理商类:


/**

* 代理商
*java学习交流:737251827  进入可领取学习资源及对十年开发经验大佬提问,免费解答!
*/

@Data
@ ToString (callSuper = true )
public class Agent extends Customer {

    /**
    * 代理周期
    */

    private int period ;

    /**
    * 代理产品
    */

    private int [ ] products ;

    public Agent ( String name , String type ) {
        super (name , type ) ;
    }
}


新增简单工厂类:

新建一个简单工厂,提供一个公共静态方法,根据不同的客户类型创建不同的客户。


/**

* 客户简单工厂
*/

public class CustomerFactory {

    private static Merchant createMerchant ( String type , String name ) {
        return new Merchant (type , name ) ;
    }

    private static BankPartner createBankPartner ( String type , String name ) {
        return new BankPartner (type , name ) ;
    }

    private static Agent createAgent ( String type , String name ) {
        return new Agent (type , name ) ;
    }

    public static Customer create ( String type , String name ) {
        if ( "M" . equals (type ) ) {
            return createMerchant (type , name ) ;
        } else if ( "B" . equals (type ) ) {
            return createBankPartner (type , name ) ;
        } else if ( "A" . equals (type ) ) {
            return createAgent (type , name ) ;
        }
        return null ;
    }

}


新建测试类:


/**

* @author:
*/

public class Test {

    public static void main ( String [ ] args ) {
       Customer merchant = CustomerFactory . create ( "M" , "Java技术栈商户" ) ;
       System .out . println (merchant ) ;

       Customer bankPartner = CustomerFactory . create ( "B" , "Java技术栈银行客户" ) ;
       System .out . println (bankPartner ) ;

       Customer agent = CustomerFactory . create ( "A" , "Java技术栈代理商" ) ;
       System .out . println (agent ) ;
    }

}


输出结果:

可以看出简单工厂的使用很简单,就是耦合性太高了。

第一,对象和基类之间是基于继承的。

第二,工厂类耦合了不同对象的创建,如果对象类型不是固定或者经常变动的,就要频繁修改工厂类,比如我现在要再加一种客户,就必须要改动工厂类,不符开闭原则。

所以,简单工厂只适用于固定类型对象的创建。

2、工厂方法

工厂方法就是为某类产品提供一个工厂接口,然后为每个产品提供一个工厂实现类。

废话少说,我们将简单工厂的示例用工厂方法再改造一下。

新建工厂方法接口:


/**

* 工厂方法客户接口
*/

public interface CustomerFactory {

   Customer create (String type , String name ) ;

}


新建商户工厂实现类:


/**

* 商户工厂
*/

public class MerchantFactory implements CustomerFactory {

   @Override
    public Customer create ( String type , String name ) {
        return new Merchant (type , name ) ;
    }

}


新建银行客户工厂实现类:


/**

* 银行客户工厂
*/

public class BankPartnerFactory implements CustomerFactory {

   @Override
    public Customer create ( String type , String name ) {
        return new BankPartner (type , name ) ;
    }

}


新建代理商工厂实现类:


/**

* 代理商工厂
*/

public class AgentFactory implements CustomerFactory {

   @Override
    public Customer create ( String type , String name ) {
        return new Agent (type , name ) ;
    }

}


新建测试类:


/**

* @author:
*/

public class Test {

    public static void main ( String [ ] args ) {
       System .out . println ( "------工厂模式-工厂方法------" ) ;

       CustomerFactory merchantFactory = new MerchantFactory ( ) ;
       Customer merchant = merchantFactory . create ( "M" , "Java技术栈商户" ) ;
       System .out . println (merchant ) ;

       CustomerFactory bankPartnerFactory = new BankPartnerFactory ( ) ;
       Customer bankPartner = bankPartnerFactory . create ( "B" , "Java技术栈银行客户" ) ;
       System .out . println (bankPartner ) ;

       CustomerFactory agentFactory   = new AgentFactory ( ) ;
       Customer agent = agentFactory . create ( "A" , "Java技术栈代理商" ) ;
       System .out . println (agent ) ;
    }

}


输出结果:

可以看出,工厂方法也是挺简单易用的,耦合性问题也解决了,每增加一个产品就新增一个产品工厂实现类就行了,扩展性非常好。

但也有一个问题,如果产品非常多,那势必会造成工厂实现类泛滥,另外一种可怕的场景就是,如果涉及到工厂接口变更,工厂实现类的维护简直就是一种恶梦。

3、抽象工厂

工厂方法中一个工厂只能创建一个对象,如果现在每次创建客户的时候都需要同时创建一份客户扩展资料,那就可以考虑使用抽象工厂。

新建客户扩展基类:


/**

* 客户扩展
*/

@Data
@NoArgsConstructor
public abstract class CustomerExt {

    /**
    * 客户曾用名
    */

    private String formerName ;

    /**
    * 客户扩展说明
    */

    private String note ;

}


新建商户扩展类:


/**

* 商户
*/

@Data
@ ToString (callSuper = true )
public class MerchantExt extends CustomerExt {

    /**
    * 介绍人
    */

    private int introduceName ;

    /**
    * 介绍人电话
    */

    private String introduceTel ;

}


新建银行客户扩展类:


/**

* 银行客户扩展
*/

@Data
@ ToString (callSuper = true )
public class BankPartnerExt extends CustomerExt {

    /**
    * 分行个数
    */

    private int branchCount ;

    /**
    * ATM个数
    */

    private int atmCount ;

}


新建代理商扩展类:


/**

* 商户
*/

@Data
@ ToString (callSuper = true )
public class AgentExt extends CustomerExt {

    /**
    * 来源
    */

    private String source ;

    /**
    * 资质
    */

    private String certification ;

}


新建抽象工厂接口:


/**

* 抽象工厂客户接口
*/

public interface CustomerFactory {

   Customer createCustomer (String type , String name ) ;

   CustomerExt createCustomerExt ( ) ;

}


新建商户工厂实现类:


/**

* 商户工厂
*/

public class MerchantFactory implements CustomerFactory {

   @Override
    public Customer createCustomer ( String type , String name ) {
        return new Merchant (type , name ) ;
    }

   @Override
    public CustomerExt createCustomerExt ( ) {
        return new MerchantExt ( ) ;
    }

}


新建银行客户工厂实现类:


/**

* 银行客户工厂
*
*/

public class BankPartnerFactory implements CustomerFactory {

   @Override
    public Customer createCustomer ( String type , String name ) {
        return new BankPartner (type , name ) ;
    }

   @Override
    public CustomerExt createCustomerExt ( ) {
        return new BankPartnerExt ( ) ;
    }

}


新建代理商工厂实现类:


/**

* 代理商工厂
*/

public class AgentFactory implements CustomerFactory {

   @Override
    public Customer createCustomer ( String type , String name ) {
        return new Agent (type , name ) ;
    }

   @Override
    public CustomerExt createCustomerExt ( ) {
        return new AgentExt ( ) ;
    }

}


新建测试类:


/**

* @author
*java学习交流:737251827  进入可领取学习资源及对十年开发经验大佬提问,免费解答!
*/

public class Test {

    public static void main ( String [ ] args ) {
       System .out . println ( "------工厂模式-抽象工厂------" ) ;

       CustomerFactory merchantFactory = new MerchantFactory ( ) ;
       Customer merchant = merchantFactory . createCustomer ( "M" , "Java技术栈商户" ) ;
       CustomerExt merchantExt = merchantFactory . createCustomerExt ( ) ;
       System .out . println (merchant ) ;
       System .out . println (merchantExt ) ;

       CustomerFactory bankPartnerFactory = new BankPartnerFactory ( ) ;
       Customer bankPartner = bankPartnerFactory . createCustomer ( "B" , "Java技术栈银行客户" ) ;
       CustomerExt bankPartnerExt = bankPartnerFactory . createCustomerExt ( ) ;
       System .out . println (bankPartner ) ;
       System .out . println (bankPartnerExt ) ;

       CustomerFactory agentFactory = new AgentFactory ( ) ;
       Customer agent = agentFactory . createCustomer ( "A" , "Java技术栈代理商" ) ;
       CustomerExt agentExt = agentFactory . createCustomerExt ( ) ;
       System .out . println (agent ) ;
       System .out . println (agentExt ) ;
    }

}

输出结果:


可以看出,抽象工厂和工厂方法十分类似,只不过抽象工厂里面只生产一个对象,而抽象工厂可以生产多个对象。抽象工厂缺点也很明显,第一就是和工厂方法一样工厂类非常多,第二就是扩展非常麻烦,比如我现在要为每个客户类型再加一份客户特殊资料,那所有涉及到抽象工厂的工厂类都要改,是不是要疯了。。

总结

如果有多个属于同一种类型的类,可以考虑使用工厂模式,统一提供生成入口,能从一定程度上解耦,扩展方便,也不用再到处 new 对象了。

但话又说回来,从示例可以看出,如果使用或者设计不当也会带来维护上的工作量。



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70010294/viewspace-2845778/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2021-11-19

  • 博文量
    199
  • 访问量
    86386