静态工厂

用一个工厂类去封装具有相同属性的其他类的new的工厂。这个方法是静态的,称之为静态工厂。

简单例子:AnimalFactory 工厂,里面生产孵化各种动物,都在这一个大工厂里

public interface Animal {
    void getAnimal();
}
class Cat implements Animal {
    @Override
    public void getAnimal() {
        System.out.println("喵喵我是一只猫");
    }
}
class Dog implements Animal {

    @Override
    public void getAnimal() {
        System.out.println("汪汪我是一只狗");
    }
}
class AnimalFactory {
    public static Animal getCat() {
        return new Cat();
    }
    public static Animal getDog() {
        return new Dog();
    }
}
class TestClass {
    public static void main(String[] agrs) {
        Animal animal =AnimalFactory.getCat();
        animal.getAnimal();
        animal =AnimalFactory.getDog();
        animal.getAnimal();
    }
}

java工厂类只能用静态方法妈 java 静态工厂_ide


      优势:

              1: 和构造器不同的第一优势在于,它们有名字,更容易知道想要表达的是啥,比如代理模式中生成代理类就是用的静态工厂方法Proxy.newProxyInstance   
                  构造器必须是类名 :比如  Cat cat =new Cat("小猫"),而静态工厂则不用,一般都后缀instance,比如 MyFactory.newOldCatInstance(),MyFactory.newYoungCatInstance()
              2:不用每次被调用时都创建新对象,减少内存开销,单例的写法也大都是用静态工厂方法来实现的
              3:可以返回原返回类型的子类       
              4:可以有多个参数相同但名称不同的工厂方法
              5:可以减少对外暴露的属性,比如上面的狗的年龄必须是1-3岁。

             如果是传统的new的方法,很有可能传入一个不符合规则的年龄,无法控制调用方

public interface Animal {
    void getAnimal();
}
class Cat implements Animal {
    @Override
    public void getAnimal() {
        System.out.println("喵喵我是一只猫");
    }
}
class Dog implements Animal {
    String dogType;
    int dogAge;
    public Dog(int dogAge, String dogType) {
        this.dogAge = dogAge;
        this.dogType = dogType;
    }
    @Override
    public void getAnimal() {
        System.out.println("汪汪我是一只狗" + dogType);
    }
}
class AnimalFactory {
    private static final int ONE_YEARS_OLD = 1;
    private static final int TWO_YEARS_OLD = 2;
    private static final int THREE_YEARS_OLD = 3;
    public static Animal getCat() {
        return new Cat();
    }
    //#########对应上面的优点1、3、4 但无法保证调用方对age输入的限制  START###########
    public static Animal getDogHsq(int age) {
        return new Dog(age, "我是哈士奇");
    }
    public static Animal getDogHsq(String dogType) {
        return new Dog(ONE_YEARS_OLD, dogType);
    }
    //#########对应上面的优点1、3、4   END###########
    //#########对应上面的优点5  START###########
    public static Animal getDogYearsOld(String dogType) {
        return new Dog(ONE_YEARS_OLD, dogType);
    }
    public static Animal getDogYearsOld2(String dogType) {
        return new Dog(TWO_YEARS_OLD, dogType);
    }
    //#########对应上面的优点5   END###########
}

想要啥动物,就继承一下Animal,直接工厂获取就行

java工厂类只能用静态方法妈 java 静态工厂_java工厂类只能用静态方法妈_02

        

缺点

            类的创建依赖工厂类,想要拓展业务需要修改工厂类,比如你想在搞一个小鸟出来,得修改AnimalFactory.java

工厂方法模式:

设计一个工厂的接口,你想要什么东西,就写个类继承于这个工厂,就好比上面的动物工厂,此时这个工厂规范化了,生产狗的新建一个车间小工厂,生产猫的新建一个车间小工厂....................

//省略上面的相关代码
//省略上面的相关代码
interface AnimalFactory{
    Animal getAnimalByFactory();
}
class DogFactory implements AnimalFactory{
    @Override
    public Animal getAnimalByFactory() {
        return  new Dog();
    }
}
class CatFactory implements AnimalFactory{
    @Override
    public Animal getAnimalByFactory() {
        return  new Cat();
    }
}

class TestClass {
    public static void main(String[] agrs) {
        Animal animal =new CatFactory().getAnimalByFactory();
        animal.getAnimal();
        animal =new DogFactory().getAnimalByFactory();
        animal.getAnimal();
    }
}

java工厂类只能用静态方法妈 java 静态工厂_System_03

如果再想生产鸟,只需要开启一个生产鸟的车间小工厂继承大工厂即可,这个大工厂是不需要动的。

缺点

           如果此时我不仅想生产动物,我想生产口罩了咋办?那么就得在AnimalFactory接口里增加  Mask getMaskByFactory,那么这样每个车间小工厂都会多出一个屋来生产口罩(因为都是同一个接口),但是其他车间小工厂是无法生产口罩的,无法在生产狗的车间小工厂生产其他物品,因为大工厂是AnimalFactory。也就是说工厂方法模式只适合来生产同一类产品。

interface AnimalFactory{
     Animal getAnimalByFactory();     Mask getMaskByFactory();
 }

 

抽象工厂模式

  把大工厂分成2类子工厂,一个是Linda的工厂,有2个车间,负责生产狗和白口罩,一个是crry的工厂,有2个车间,负责生产猫和黑口罩。

  如果想在生产汽车,那么就新建一个join工厂。

此时有3个子工厂:Linda的工厂,3个车间,负责生产狗和白口罩和汽车。carry的工厂,3个车间,负责生产猫和黑口罩和汽车。join工厂,3个车间,一个生产汽车,其他2个随意。

因为他们都在大工厂Factory里的,所以再开辟其他工厂很简单。工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

动物接口及实现类

public interface Animal {
    void getAnimal();
}

class Cat implements Animal {
    @Override
    public void getAnimal() {
        System.out.println("喵喵我是一只猫");
    }
}

class Dog implements Animal {

    @Override
    public void getAnimal() {
        System.out.println("汪汪我是一只狗");
    }
}

口罩接口及实现类

interface Mask {
    void getMask();
}

class BlackMask implements Mask {
    @Override
    public void getMask() {
        System.out.println("我是一个黑口罩");
    }
}

class WhiteMask implements Mask {

    @Override
    public void getMask() {
        System.out.println("我是一个白口罩");
    }
}

生产动物和口罩的接口

interface Factory {
    Animal getAnimalByFactory();
    Mask getMaskByFactory();
}

生产动物和口罩的实现类

class FactoryOfLinda implements Factory {

    @Override
    public Animal getAnimalByFactory() {
        return new Dog();
    }
    @Override
    public Mask getMaskByFactory() {
        return new BlackMask();
    }
}

class FactoryOfCarry implements Factory {

    @Override
    public Animal getAnimalByFactory() {
        return new Cat();
    }
    @Override
    public Mask getMaskByFactory() {
        return new WhiteMask();
    }
}

调用

class TestClass {
    public static void main(String[] agrs) {
        // linda 想生产一只狗
        Factory factory = new FactoryOfLinda();
        Animal animal = factory.getAnimalByFactory();
        animal.getAnimal();
        // carry想生产一只猫 只需要改动把FactoryOfLinda 换成FactoryOfCarry即可
        factory = new FactoryOfCarry();
        animal = factory.getAnimalByFactory();
        animal.getAnimal();

        // linda 想生产一个口罩
        factory = new FactoryOfLinda();
        Mask mask = factory.getMaskByFactory();
        mask.getMask();
    }
}

java工厂类只能用静态方法妈 java 静态工厂_System_04

总结:

简单工厂:所有的东西都是一个大工厂生产,压力比较大,想扩展必须修改大工厂。

工厂方法:大工厂里面细分了车间小工厂,解决了简单工厂的缺点,但是只能生产一类东西。

抽象工厂:对工厂方法进行了更高的抽象,大工厂分为不同类型的子工厂,子工厂进行车间的划分。

===========================分割线============================================

抽象工厂常用场景是一个项目工程里使用了不同的数据库比如mysql、oracle等,需要动态切换不同的库,每个库的sql也不一定一样。

对于抽象工厂虽然解决了不少问题,但是如果大工厂接口进行了改变,那么下面的子工厂必须实现大工厂的方法,比如上面的生产汽车,下面的子工厂必须都生产汽车。

但是jdk1.8解决了上面的问题,jdk1.8新特性默认方法,允许接口里定义默认方法,如果子类的操作都一样,那么就不用实现此方法,由接口来统一处理

java工厂类只能用静态方法妈 java 静态工厂_ide_05