简单工厂模式

概述


在常规的软件开发中,通常存在分层的概念,例如:MVC分层,TCP/IP层次模型等。在分层结构中,一般为高层结构依赖较低层次的模块进行实现,但是低层次模块不允许调用高层模块的代码,其依赖关系可以表示为下图:

简单工厂模式_第1张图片

常见的情景就是数据库连接库的使用。在开发数据库相关应用时,如果在高层模块中显式调用数据库连接的代码,将底层模块提供的api耦合于高层模块中,当需修改将数据库提供商(mysql, oracle,redis等)、数据库连接参数等时,则会导致需要修改的代码量过大,细节过多的问题。而当我们在开发其它项目,但是逻辑基本相同时,也无法复用以前项目的代码,增加开发成本。因此在人们的实践过程中,发展出了各种编码的技巧,以达到低耦合、可复用的目的,并总结成多个设计模式。

但是设计模式不是银弹,在编码的过程中,不要迷信设计模式。根据自己项目的需求和特性,适当使用,而不滥用才是我们学习设计模式的目的


不使用设计模式


代码展示


public class Product1 {
    public void create() {
        System.out.println("Product 1 is created...");
    }
}

public class Product2 {
    public void create() {
        System.out.println("Product 2 is created...");
    }
}

public class Product3 {
    public void create() {
        System.out.println("Product 3 is created...");
    }
}

public class Product4 {
    public void create() {
        System.out.println("Product 4 is created...");
    }
}

public class User {
    public static final void main(String[] args) {
        Product1 product1 = new Product1();
        product1.create();
        Product2 product2 = new Product2();
        product2.create();
        Product3 product3 = new Product3();
        product3.create();
        Product4 product4 = new Product4();
        product4.create();
    }
}

类图展示


简单工厂模式_第2张图片

说明


通过上面的代码和类图,我们可以看到,高层组件User直接依赖于同一种底层组件的具体实现类,就像高层组件直接调用了底层数据库提供的方法。当User中需要更改引用的底层组件时,则需要显式修改高层模块的代码,如将Product1的引用修改成Product2的引用。当Product1在多处被引用时,修改时的弊端就会更加明显。

在以上的代码中,我们发现,用户编码的目的就是为了生成一个产品,并调用它的创建方法。我们发现只是在生成对象时的代码不同,
最后都是调用了create()方法。既然基本的逻辑相同,是否可以使用Java中的抽象概念,将代码的可用性提升一些?当然可以,我们将代码改进一下。


第一次改进代码


代码展示



public interface Product {
    void create();
}

public class Product1 implements Product {
    public void create() {
        System.out.println("Product 1 is created...");
    }
}

public class Product2  implements Product {
    public void create() {
        System.out.println("Product 2 is created...");
    }
}

public class Product3 implements Product {
    public void create() {
        System.out.println("Product 3 is created...");
    }
}

public class Product4 implements Product {
    public void create() {
        System.out.println("Product 4 is created...");
    }
}

public class User {
    public Product createProduct(String type) {
        Product product = null;
        switch (type) {
            case "product1":
                product = new Product1();
                break;
            case "product2":
                product = new Product2();
                break;
            case "product3":
                product = new Product3();
                break;
            case "product4":
                product = new Product4();
                break;
        }
        System.out.println("Hello, this is a user... I have a product " + product);
        return product;
    }

    public void method2() {

    }

    public static final void main(String[] args) {
        User user = new User();
        Product product = user.createProduct("product1");
        product.create();
    }
}

类图


简单工厂模式_第3张图片


说明


在这次修改中,我们首先将原有的代码进行抽象,使得User不再依赖于Product接口,而不是具体实现。在User的方法中,传入一个类型参数,供main方法调用,通过传入不同的类型,生成不同的产品。

但是,这种实现方式仍然有一些不足: (1) 如果新增一个产品Product5,需要修改User中的代码,这违背了软件设计中的单一职责原则。(2) 在createProduct方法中,User可能有其它的处理逻辑需要使用product对象;(3) User仍然与Product关联,当其它模块需要生成一个Product时,难道需要同时生成一个User对象?这显然是不合理的。因此我们需要再将代码修改一下。

第二次修改


代码展示



public class ProductFactory {
    public static Product create(String type) {
        Product product = null;
        switch (type) {
            case "product1":
                product = new Product1();
                break;
            case "product2":
                product = new Product2();
                break;
            case "product3":
                product = new Product3();
                break;
            case "product4":
                product = new Product4();
                break;
        }
        return product;
    }
}

public class User {
    public Product createProduct(String type) {
        Product product = ProductFactory.create(type);
        System.out.println("Hello, this is a user... I have a product " + product);
        return product;
    }

    public void method2() {

    }

    public static final void main(String[] args) {
        User user = new User();
        Product product = user.createProduct("product1");
        product.create();
    }
}

UML展示


简单工厂模式_第4张图片


说明


在上述的实现方法中,User不再直接依赖Product,而是通过一个工厂类ProductFactory产生对应的Product对象。该对象弥补了第一次修改时的缺点,当需要生成新的一中Product时,则只需要集中在ProductFactory进行简单的修改即可。当其它类需要生成Product对象时,只需要调用工厂中的方法即可,而不用担心对应的逻辑侵入的问题。


总结


以上介绍的就是工厂模式中最简单的静态工厂模式。用于生产对应产品的类称为工厂类,用于生成对应产品的方法为工厂方法。一般情况下,工厂方法中,除根据参数(可以是类型、名称等)生成对应的产品对象外,不包含其它的逻辑处理。并且该工厂可以在在其它的业务类中引用,而不用 担心逻辑的侵入问题。例如,将数据库连接生成操作进行封装,根据传入的参数,生成针对不同的数据库的连接。当高层模块进行复用时,只需要修改数据库连接工厂中的方法即可,而不用大面积的修改高层模块的业务代码,从而降低高层模块与底层模块的耦合性。

你可能感兴趣的:(设计模式系列)