一天一种JAVA设计模式之二:工厂模式

265 阅读8分钟

写在前面的话

复习、总结23种设计模式

获取详细源码请点击我

工厂模式可以分为3类:

  1. 简单工厂模式:一般就一个工厂类,它负责生产所有的对象(通过传入的参数不同生产不同对象)
  2. 工厂方法模式:通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建(一个工厂接口 + 多个具体工厂类)
  3. 抽象工厂模式:在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象

1.简单工厂模式

定义

定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。

eg:今天我们要作为造物主造人了

首先我们必须要有一个人这个接口Person,具体的分为:男人Man,女人Woamn,还有其他的Other

public abstract class Person {  
    abstract void run();  
}  
  
class Man extends Person {  
  
    void run() {  
        System.out.println("man run");  
    }  
}  
  
class Woman extends Person {  
  
    void run() {  
        System.out.println("woman run");  
    }  
}  
  
class Other extends Person {  
  
    void run() {  
        System.out.println("other run");  
    }  
}

第二步我们必须要有一个工厂,它是为了专门造人而存在的,他可以生产男人、女人和其他人

public class PersonFactory {  
    public static Person create(String type) {  
        if ("man".equals(type)) {  
            return new Man();  
        } else if ("woman".equals(type)) {  
            return new Woman();  
        }  
        return new Other();  
    }  
}

好了,我们工厂有了,人也定义好了,可以来造人试一试了

/*  
简单工厂模式的定义:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口  
缺陷:
1.工厂产生的对象的种类不能太多,要不然业务逻辑就太复杂了;  
2.因为输入参数时用户可能会写错,如果写错了,那么工厂就不能返回正确的示例对象了(这种方式可以定义枚举来解决)  
3.另外如果想创建一种新的Person对象,就需要修改PersonFactory的产生对象逻辑,这就违反了设计模式的六大原则之一:开闭原则(对扩展开放,对修改关闭)(可以通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建)  
*/
public class Test01简单工厂模式 {  
  
    public static void main(String[] args) {  

        Person man = PersonFactory.create("man");  
        man.run();  

        Person woman = PersonFactory.create("woman");  
        woman.run();  
    }  
}

截至目前为止,简单工厂模式DEMO已经完成了,我们来看看他有什么缺陷没有。

  1. 截止目前为止,世界上人的性别不止有这三种,据统计不下于100种呢?如果我们的造人工厂真的像造出这么多的人,那么必然会导致PersonFactory.create(String)中逻辑复杂;
  2. 如果我们在造人的时候传入的参数错误,是不是就会导致造出来的人都不是我们想要的(这种方式可以定义枚举来解决);
  3. 另外如果想创建一种新的Person对象,就需要修改PersonFactory的产生对象逻辑,这就违反了设计模式的六大原则之一:开闭原则(对扩展开放,对修改关闭)(可以通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建,这种方式就是工厂方法模式

2.工厂方法模式

定义

通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建(一个工厂接口 + 多个具体工厂类)

和简单工厂比对

最根本的区别:

  • 简单工厂模式只有一个统一的工厂类,
  • 工厂方法模式是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类(本例中的CarFactory)

eg:造车

我们今天来造车,具体的有自行车和火车,他们都是车子

package com.design.pattern.test02;  
  
// 车子  
public interface Car {  
  
    void run();  
}  
  
// 自行车  
class BicycleCar implements Car {  
    public void run() {  
        System.out.println("bicycle car");  
    }  
}  
// 火车  
class TrainCar implements Car {  
    public void run() {  
        System.out.println("train car");  
    }  
}

第二步我们建厂(抽象)了来生产车子(抽象),厂子(抽象)可以分为自行车厂和火车厂(具体)

package com.design.pattern.test02;  
  
// 厂子  
public interface CarFactory {  
    // 生产车子,具体是哪一种车子交给子类  
    Car create();  
  
}  
  
// 自行车厂  
class BicycleCarFactory implements CarFactory{  
  
    public Car create() {  
        return new BicycleCar();  
    }  
}  
  
// 火车厂  
class TrainCarFactory implements CarFactory{  
    public Car create() {  
        return new TrainCar();  
    }  
}

好了,我们现在自行车厂和火车厂都有了,开始造车了(使用不同的厂子来造不同的车子),如果我们还想生产轮船,我们就再建一个轮船工厂,这样自行车工厂和火车工厂都不需要任何改动,符合开闭原则

package com.design.pattern.test02;  
  
/*  
工厂方法模式:通过不同的工厂来创建不同的对象,每个对象有对应的工厂创建(一个工厂接口 + 多个具体工厂类)  
和简单工厂对比一下,最根本的区别在于简单工厂模式只有一个统一的工厂类,  
而工厂方法模式是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类(本例中的CarFactory)  
*/  
public class Test02工厂方法模式 {  
  
    public static void main(String[] args) {  
        // 生产自行车我们就使用自行车工厂  
        CarFactory bicycleCarFactory = new BicycleCarFactory();  
        Car bicycleCar = bicycleCarFactory.create();  
        bicycleCar.run();  

        // 生产火车我们就使用火车工厂  
        CarFactory trainCarFactory = new TrainCarFactory();  
        Car trainCar = trainCarFactory.create();  
        trainCar.run();  

        // 如果我们还想生产轮船,我们就新建一个轮船工厂,这样自行车工厂和火车工厂都不需要任何改动,符合开闭原则  
    }  
  
}

3.抽象工厂模式

定义

抽象工厂模式是工厂方法模式的升级版,它定义了多个工厂接口和多个产品族接口, 每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。
客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换,符合开闭原则

eg:造人

肤色定义

package com.design.pattern.test04;

// 肤色  
public interface Color {  
    String display();  
}  
  
    class Yellow implements Color {  

        public String display() {  
            return "黄种人";  
        }  
    }  

    class Black implements Color {  
        public String display() {  
            return "黑种人";  
        }  
    }  

    class White implements Color {  

        public String display() {  
          return "白种人";  
        }  

}

性别

package com.design.pattern.test04;  
  
public interface Sex {  
  
    String control();  
  
}  
  
    class Man implements Sex {  

        public String control() {  
            return "男";  
        }  

    }  

    class Woman implements Sex {  

        public String control() {  
            return "女";  
        }  
    }  

    class Other implements Sex {  

        public String control() {  
            return "你猜";  
        }  
    }

建厂了

package com.design.pattern.test04;  
  
public interface PersonFactory {  
  
    // 生产出性别sex  
    Sex deciceSex();  

    // 生产出肤色color  
    Color decideColor();  
}  

    class ManYellowFactory implements PersonFactory {  

        public Sex deciceSex() {  
            return new Man();  
        }  

        public Color decideColor() {  
            return new Yellow();  
        }  
    }  

    class WomanBlackFactory implements PersonFactory {  

        public Sex deciceSex() {  
            return new Woman();  
        }  

        public Color decideColor() {  
            return new Black();  
        }  
    }

实践出真知,来造人吧

package com.design.pattern.test04;  
/*  
  
*/  
public class Test04抽象工厂模式 {  
  
    public static void main(String[] args) {  
        // 黄种男性  
        {  
            // 获取生产黄种男性的工厂  
            PersonFactory manYellowFactory = new ManYellowFactory();  
            // 生产男性  
            Sex sex = manYellowFactory.deciceSex();  
            // 生产黄皮肤  
            Color color = manYellowFactory.decideColor();  

            sex.control();  
            color.display();  
        }  
        
        // 黑皮肤女性  
        {  
            WomanBlackFactory womanBlackFactory = new WomanBlackFactory();  
            // 生产女性  
            Sex sex = womanBlackFactory.deciceSex();  
            // 生产黑皮肤  
            Color color = womanBlackFactory.decideColor();  

            sex.control();  
            color.display();  
        }  
    }  
}

和工厂方法模式区别

**Java 中的工厂方法模式和抽象工厂模式都是创建型设计模式,它们的主要目的都是封装对象的创建过程,将对象的创建和使用分离开来,简单工厂是工厂方法模式的特例。 **

1.创建对象的方式不同

  • 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换。
  • 抽象工厂模式:抽象工厂模式定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换。

2. 创建的对象类型不同

  • 工厂方法模式:工厂方法模式适用于创建多种类型的产品对象。
  • 抽象工厂模式:抽象工厂模式适用于创建多个产品族的对象。

3. 代码结构不同

  • 工厂方法模式:工厂方法模式通常只需要一个工厂接口和多个具体工厂类,客户端只需要调用工厂接口的方法即可创建对象。
  • 抽象工厂模式:抽象工厂模式需要定义多个工厂接口和产品族接口,每个工厂接口和产品族接口都需要对应多个具体实现类,代码结构更加复杂。

工厂模式总结

简单工厂模式适用于创建单一类型的产品对象,
工厂方法模式适用于创建多种类型的产品对象,
抽象工厂模式适用于创建多个产品族的对象。