你还在到处 new 对象吗?

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

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

什么是工厂模式?

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

工厂模式的益处是这些对象不须要裸露本身的创立过程,对立由工厂模式进行创立和提供,暗藏了创立细节,防止了谬误的创建对象的模式,也缩小了反复创立冗余代码。

个别状况下,工厂模式能够细分为三类:

  • 简略工厂模式
  • 工厂办法模式
  • 形象工厂模式

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

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

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

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

1、简略工厂

比方 XX 公司是做领取的,公司有几大类的客户:电商商户、银行客户、代理商……

创立这些客户的时候咱们能够用简略工厂模式来实现看看。

新建客户基类:

能够把所有客户公共的信息放到一个客户基类中,比方:客户名、客户类型等,所有的客户继承这个形象基类。

/** * 客户 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@NoArgsConstructor@AllArgsConstructorpublic abstract class Customer {    /**     * 客户名称     */    private String name;    /**     * 客户类型     */    private String type;}

新建电商商户类:

/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class Merchant extends Customer {    /**     * 合同类型     */    private int contractType;    /**     * 结算周期(天)     */    private int settmentDays;    public Merchant(String name, String type) {        super(name, type);    }}

新建银行客户类:

/** * 银行客户 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class BankPartner extends Customer {    /**     * 银行编码     */    private String code;    /**     * 银行地址     */    private String address;    public BankPartner(String name, String type) {        super(name, type);    }}

新建代理商类:

/** * 代理商 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class Agent extends Customer {    /**     * 代理周期     */    private int period;    /**     * 代理产品     */    private int[] products;    public Agent(String name, String type) {        super(name, type);    }}

新增简略工厂类:

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

/** * 客户简略工厂 * @author: 栈长 * @from: 公众号Java技术栈 */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: 栈长 * @from: 公众号Java技术栈 */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);    }}

输入后果:

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks...

能够看出简略工厂的应用很简略,就是耦合性太高了。

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

第二,工厂类耦合了不同对象的创立,如果对象类型不是固定或者常常变动的,就要频繁批改工厂类,比方我当初要再加一种客户,就必须要改变工厂类,不符开闭准则。

所以,简略工厂只实用于固定类型对象的创立。

2、工厂办法

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

废话少说,咱们将简略工厂的示例用工厂办法再革新一下。

新建工厂办法接口:

/** * 工厂办法客户接口 * @author: 栈长 * @from: 公众号Java技术栈 */public interface CustomerFactory {    Customer create(String type, String name);}

新建商户工厂实现类:

/** * 商户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */public class MerchantFactory implements CustomerFactory {    @Override    public Customer create(String type, String name) {        return new Merchant(type, name);    }}

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

/** * 银行客户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */public class BankPartnerFactory implements CustomerFactory {    @Override    public Customer create(String type, String name) {        return new BankPartner(type, name);    }}

新建代理商工厂实现类:

/** * 代理商工厂 * @author: 栈长 * @from: 公众号Java技术栈 */public class AgentFactory implements CustomerFactory {    @Override    public Customer create(String type, String name) {        return new Agent(type, name);    }}

新建测试类:

/** * @author: 栈长 * @from: 公众号Java技术栈 */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);    }}

输入后果:

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks...

能够看出,工厂办法也是挺简略易用的,耦合性问题也解决了,每减少一个产品就新增一个产品工厂实现类就行了,扩展性十分好。

但也有一个问题,如果产品十分多,那势必会造成工厂实现类泛滥,另外一种可怕的场景就是,如果波及到工厂接口变更,工厂实现类的保护几乎就是一种恶梦。

3、形象工厂

工厂办法中一个工厂只能创立一个对象,如果当初每次创立客户的时候都须要同时创立一份客户扩大材料,那就能够思考应用形象工厂。

新建客户扩大基类:

能够把所有客户公共的扩大信息放到一个客户扩大基类中,比方:客户曾用名、客户扩大阐明等,所有的客户继承这个扩大形象基类。

/** * 客户扩大 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@NoArgsConstructorpublic abstract class CustomerExt {    /**     * 客户曾用名     */    private String formerName;    /**     * 客户扩大阐明     */    private String note;}

新建商户扩大类:

/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class MerchantExt extends CustomerExt {    /**     * 介绍人     */    private int introduceName;    /**     * 介绍人电话     */    private String introduceTel;}

新建银行客户扩大类:

/** * 银行客户扩大 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class BankPartnerExt extends CustomerExt {    /**     * 分行个数     */    private int branchCount;    /**     * ATM个数     */    private int atmCount;}

新建代理商扩大类:

/** * 商户 * @author: 栈长 * @from: 公众号Java技术栈 */@Data@ToString(callSuper = true)public class AgentExt extends CustomerExt {    /**     * 起源     */    private String source;    /**     * 资质     */    private String certification;}

新建形象工厂接口:

/** * 形象工厂客户接口 * @author: 栈长 * @from: 公众号Java技术栈 */public interface CustomerFactory {    Customer createCustomer(String type, String name);    CustomerExt createCustomerExt();}

新建商户工厂实现类:

/** * 商户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */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();    }}

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

/** * 银行客户工厂 * @author: 栈长 * @from: 公众号Java技术栈 */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();    }}

新建代理商工厂实现类:

/** * 代理商工厂 * @author: 栈长 * @from: 公众号Java技术栈 */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: 栈长 * @from: 公众号Java技术栈 */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 对象了。

但话又说回来,从示例能够看出,如果应用或者设计不当也会带来保护上的工作量。

本节教程所有实战源码已上传到这个仓库:

https://github.com/javastacks...

好了,明天的分享就到这里了,前面栈长我会更新其余设计模式的实战文章,公众号Java技术栈第一工夫推送。Java技术栈《设计模式》系列文章陆续更新中,请大家继续关注哦!

最初,感觉我的文章对你用播种的话,动动小手,给个在看、转发,原创不易,栈长须要你的激励。

版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、援用本文内容请注明出处,禁止剽窃、洗稿,请自重,尊重大家的劳动成果和知识产权,剽窃必究。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2021最新版)

2.终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!