原创

【java设计模式】简单工厂、工厂方法、抽象工厂模式

简单理解工厂模式

妹子最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞定,这就是我的“我爱你”builder。(这一定比美军在伊拉克用的翻译机好卖)

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”(在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。)

工厂模式的作用

解耦 :把对象的创建使用的过程分开

降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。

降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。

工厂模式的分类

  • 简单工厂模式(Simple Factory)
    又称静态工厂方法模式(Static Factory Method Pattern)
  • 工厂方法模式(Factory Method)
    又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式
  • 抽象工厂模式(Abstract Factory)
    又称工具箱(Kit 或Toolkit)模式

简单工厂模式

简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。

例:

创建一个宠物接口

public interface Pet {
    void say();
}

创建实现该接口的宠物实体类(猫、狗、鸟)

public class Cat implements Pet {
    public void say() {
        System.out.println("我是一只猫,喵喵喵");
    }
}
public class Dog implements Pet {
    public void say() {
        System.out.println("我是一只狗,汪汪汪");
    }
}
public class Bird implements Pet {
    public void say() {
        System.out.println("我是一只鸟,叽叽叽喳喳喳");
    }
}

创建要给宠物实体工厂类,根据给定的信息生成宠物实体类对象

public class PetsFactory {
    public static Pet createPet(String type){
        Pet pet = null;
        if ("Cat".equals(type)){
            return new Cat();
        }else if ("Dog".equals(type)){
            return new Dog();
        }else if ("Bird".equals(type)){
            return new Bird();
        }
        return pet;
    }
}

测试一下

public class Test {
    public static void main(String[] args) {
        Pet cat = PetsFactory.createPet("Cat");
        Pet dog = PetsFactory.createPet("Dog");
        Pet bird = PetsFactory.createPet("Bird");

        cat.say();
        dog.say();
        bird.say();
    }
}

结果

我是一只猫,喵喵喵
我是一只狗,汪汪汪
我是一只鸟,叽叽叽喳喳喳

这样会有一个问题,如果我们新增了一个种类的宠物,比如兔子,我们就要修改工厂类的 createPet() 方法,违背了开放封闭原则

使用反射机制来改善简单工厂

新的工厂类

public class PetsFactory2 {
    public static Object getClass(Class<? extends Pet> clazz){
        Object obj = null;
        try {
            obj = Class.forName(clazz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;
    }
}

新增兔子

public class Rabbit implements Pet{
    public void say() {
        System.out.println("我是一只兔子,我好像不会叫");
    }
}

测试

public class Test2 {
    public static void main(String[] args) {
        Cat cat = (Cat) PetsFactory2.getClass(Cat.class);
        cat.say();

        Dog dog = (Dog) PetsFactory2.getClass(Dog.class);
        dog.say();

        Bird bird = (Bird) PetsFactory2.getClass(Bird.class);
        bird.say();

        Rabbit rabbit = (Rabbit) PetsFactory2.getClass(Rabbit.class);
        rabbit.say();
    }
}

结果

我是一只猫,喵喵喵
我是一只狗,汪汪汪
我是一只鸟,叽叽叽喳喳喳
我是一只兔子,我好像不会叫

工厂方法模式

在工厂方法模式中,每个对象都有一个与之对应的工厂

例:

简单工厂例子中的宠物接口相关实现类保留不变
增加工厂接口

public interface PetFactory {
    public Pet getPet();
}

增加工厂类,实现工厂接口

public class CatFactory implements PetFactory{
    public Pet getPet() {
        return new Cat();    //返回猫
    }
}
public class DogFactory implements PetFactory{
    public Pet getPet() {
        return new Dog();    //返回狗
    }
}
public class BirdFactory implements PetFactory{
    public Pet getPet() {
        return new Bird();    //返回鸟
    }
}

测试一下

public class Test {
    public static void main(String[] args) {
        PetFactory catFactory = new CatFactory();
        catFactory.getPet().say();

        PetFactory dogFactory = new DogFactory();
        dogFactory.getPet().say();

        PetFactory birdFactory = new BirdFactory();
        birdFactory.getPet().say();
    }
}

结果

我是一只猫,喵喵喵
我是一只狗,汪汪汪
我是一只鸟,叽叽叽喳喳喳

抽象工厂模式

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。拿宠物店来比较,工厂方法模式的宠物店只卖宠物,想要买饲料还要去工厂方法模式的饲料店。抽象工厂模式的宠物店不仅卖宠物,还卖饲料,甚至还给宠物看病。这样铲屎官们就不用为了自家主子东奔西走了

例:

宠物接口相关实现类保留不变
创建工厂接口

public interface PetFactory {
    public Pet buyPet();
    public Food buyFood();
}

具体工厂

public class CatFactory implements PetFactory{
    public Pet buyPet() {
        return new Cat();
    }
    
    public Food buyFood() {
        return new CatFood();
    }
}
public class DogFactory implements PetFactory{
    public Pet buyPet() {
        return new Dog();
    }

    public Food buyFood() {
        return new DogFood();
    }
}
public class BirdFactory implements PetFactory{
    public Pet buyPet() {
        return new Bird();
    }

    public Food buyFood() {
        return new BirdFood();
    }
}

测试一下

public class Test {
    public static void main(String[] args) {
        PetFactory factory;
        Food food;
        Pet pet;

        factory = new CatFactory();
        food = factory.buyFood();
        pet = factory.buyPet();
        food.feed();
        pet.say();

        factory = new DogFactory();
        pet = factory.buyPet();
        food = factory.buyFood();
        food.feed();;
        pet.say();

        factory = new BirdFactory();
        pet = factory.buyPet();
        food = factory.buyFood();
        food.feed();
        pet.say();
    }
}

结果

猫粮喂给猫咪
我是一只猫,喵喵喵
狗粮喂给狗狗
我是一只狗,汪汪汪
虫子喂给小鸟
我是一只鸟,叽叽叽喳喳喳
正文到此结束
本文目录