【java设计模式】简单工厂、工厂方法、抽象工厂模式(创建型模式)

工厂模式的作用


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

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

降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象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 Food {
    public void feed();
}
public class DogFood implements Food{
    public void feed() {
        System.out.println("狗粮喂给狗狗");
    }
}
public class CatFood implements Food{
    public void feed() {
        System.out.println("猫粮喂给猫咪");
    }
}
public class BirdFood implements Food{
    public void feed() {
        System.out.println("虫子喂给小鸟");
    }
}
public class RabbitFood implements Food{
    public void feed() {
        System.out.println("胡萝卜喂给兔子");
    }
}

创建工厂接口

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();
    }
}

结果

猫粮喂给猫咪
我是一只猫,喵喵喵
狗粮喂给狗狗
我是一只狗,汪汪汪
虫子喂给小鸟
我是一只鸟,叽叽叽喳喳喳

简单工厂改造抽象工厂


public class PetFactory {
    private String petName;

    public PetFactory(String petName) {
        this.petName = petName;
    }

    public Pet getPet(){
        Pet pet = null;
        switch (petName) {
            case "bird":
                pet = new Bird();
                break;
            case "cat":
                pet = new Cat();
                break;
            case "dog":
                pet = new Dog();
                break;
        }
        return pet;
    }

    public Food getFood(){
        Food food = null;
        switch (petName) {
            case "bird":
                food = new BirdFood();
                break;
            case "cat":
                food = new CatFood();
                break;
            case "dog":
                food = new DogFood();
                break;
        }
        return food;
    }
}
public class Test {
    public static void main(String[] args) {
        PetFactory petFactory;
        Pet pet;
        Food food;

        petFactory = new PetFactory("cat");
        pet = petFactory.getPet();
        food = petFactory.getFood();
        food.feed();
        pet.say();

        petFactory = new PetFactory("bird");
        pet = petFactory.getPet();
        food = petFactory.getFood();
        food.feed();
        pet.say();


        petFactory = new PetFactory("dog");
        pet = petFactory.getPet();
        food = petFactory.getFood();
        food.feed();
        pet.say();
    }
}

反射改造的抽象工厂


新增产品不用修改工厂方法,但对类名有一致性要求。

public class PetFactory {
    private String petName;

    public PetFactory(String petName) {
        this.petName = petName;
    }

    public Pet getPet() {
        String packageName = "com.example.pet.";
        String clazzName = packageName + petName;
        Pet pet = null;
        try {
            Class clazz = Class.forName(clazzName);
            pet = (Pet) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return pet;
    }

    public Food getFood() {
        String packageName = "com.example.food.";
        String suffix = "Food";
        String clazzName = packageName + petName + suffix;
        Food food = null;
        try {
            Class clazz = Class.forName(clazzName);
            food = (Food) clazz.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return food;
    }
}
public class Test {
    public static void main(String[] args) {
        PetFactory petFactory;
        Food food;
        Pet pet;

        petFactory = new PetFactory("Dog");
        food = petFactory.getFood();
        pet = petFactory.getPet();
        food.feed();
        pet.say();

        petFactory = new PetFactory("Cat");
        food = petFactory.getFood();
        pet = petFactory.getPet();
        food.feed();
        pet.say();

        petFactory = new PetFactory("Rabbit");
        food = petFactory.getFood();
        pet = petFactory.getPet();
        food.feed();
        pet.say();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值