Java设计模式——三种工厂模式

一、简单工厂模式

1.1、基本介绍

  • 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个简单工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单使用的模式。
  • 简单工厂模式:定义一个创建对象的类,由这个类来封装实例化对象的行为。
  • 使用场景:在软件开发中,当我们需要大量创建某种对象时,就会使用该模式。

1.2、举例演示

  • 例子:一家披萨店,现在推出奶酪披萨、胡椒披萨……。现在利用工厂模式做一个点餐系统。

1.3、案例需求分析

  • 我们假设每个披萨的制作流程都是一样的,即:原材料的准备(每一种披萨的原料不同)、烘烤、切割、打包。由于每种披萨的原料不同,所以需要将该类做成抽象类。然后让其他种类披萨去继承这个类。
  • 我们接着建造一个工厂,用来生产这个店里面所有种类的披萨。并且这个工厂要依赖所以种类的披萨。
  • 最后,我们让餐馆和这个工厂产生依赖,去进行点餐行为。

1.4、类图设计

在这里插入图片描述

1.5、代码展示

  • 首先,我们写出披萨的抽象类。
public abstract class Pizza {
    public String name;//披萨名称

    public abstract void prepare();

    public void back() {
        System.out.println(name + "开始烘烤");
    }

    public void cut() {
        System.out.println(name + "开始切割");
    }

    public void box() {
        System.out.println(name + "开始打包");
    }
}
  • 然后去实现各种类型的披萨。(为了方便,下面我将所有类型的披萨类写在一起,如果复制代码,需要注意,不要直接将所有复制在一个类里面);
//奶酪披萨
public class Cheese extends Pizza {
    public Cheese() {
        name = "奶酪披萨";
    }
    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}
//胡椒披萨
public class Pepper extends Pizza {
    public Pepper() {
        name = "胡椒披萨";
    }

    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}
  • 披萨准备好后,我们就需要建立工厂去生产。
public class Factory {
//通过接收输入的披萨种类,进行披萨的生产
    public Pizza creatPizza(String type) {
		Pizza pizza = null;
        if ("pepper".equals(type)) {
            pizza =  new Pepper();
        }else if ("cheese".equals(type)) {
            pizza = new Cheese();
        }

        return pizza;
    }
}
  • 最后,进行点餐
public class OrderPizza {

    public void order(Factory factory) {
        String type = null;
        Pizza pizza = null;

        do{
            type = getType();
            pizza = factory.creatPizza(type);
//如果返回null,说明这个工厂不能生产输入类型的披萨,或者该种类的披萨不存在。
            if (null == pizza) {
                System.out.println("没有该类型披萨");
                break;
            }

            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }while(true);
    }
//这个方法需要注意,他是用来获取输入披萨类型的,
    public String getType() {
        String type = null;

        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("输入披萨类型:");
            type = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return type;
    }
}
  • 最后,我们终于可以开始吃披萨了;
public class Test {
    public static void main(String[] args) {
        new OrderPizza().order(new Factory());
    }
}

二、工厂方法模式

2.1、基本介绍

  • 工厂方法模式:定义一个创建对象的的抽象方法,由子类决定要实例化的类,工厂方法模式将对象的实例化推迟到子类。

2.2、举例演示

  • 在上一个项目基础上添加新的需求。客户在点披萨时可以点不同地区口味的,比如北京的奶酪披萨、伦敦的奶酪披萨。都是奶酪披萨,但是不同地区口味不同。

2.3、案例分析

  • 有的人可能会说,这个用简单工厂模式不就可以解决了。但是,如果那样做,就会产生一个问题问题,类爆炸。想想全世界,要有多少种不同的披萨,那么,factory里面的条件判断要写多少条呀。想想都觉得可怕。这样会给后期软件的维护、可扩展性会带来问题。
  • 解决方案: 将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

2.4、类图设计

在这里插入图片描述

2.5、代码展示

  • Pizza抽象类和上面一样,这里就不再写了。
  • 不同地区口味的披萨种类,
public class BJCheese extends Pizza {
    public BJCheese() {
        name = "北京奶酪披萨";
    }
    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}

public class BJPepper extends Pizza {
    public BJPepper() {
        name = "北京胡椒披萨";
    }

    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}

public class LDCheese extends Pizza {
    public LDCheese() {
        name = "伦敦奶酪披萨";
    }
    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}

public class LDPepper extends Pizza {
    public LDPepper() {
        name = "伦敦胡椒披萨";
    }

    @Override
    public void prepare() {
        System.out.println("开始准备" + name);
    }
}
  • 抽象工厂
public abstract class Factory {
    public abstract Pizza creatPizza(String type);

    public void order() {
        String type = null;
        Pizza pizza = null;
        while (true) {
            type = getType();
            pizza = creatPizza(type);

            if (null == pizza) {
                System.out.println("没有该类披萨");
                break;
            }
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }
    }

    private String getType() {
        String type = null;

        try {
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨类型:");
            type = bf.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return type;
    }
}
  • 具体工厂
//北京的制作店铺
public class BJStory extends Factory {
    @Override
    public Pizza creatPizza(String type) {
        Pizza pizza = null;

        if ("cheese".equals(type)) {
            pizza = new BJCheese();
        }else if("pepper".equals(type)) {
            pizza = new BJPepper();
        }

        return pizza;
    }
}

//伦敦的制作店铺
public class LDStore extends Factory {
    @Override
    public Pizza creatPizza(String type) {
        Pizza pizza = null;
        if ("pepper".equals(type)) {
            pizza = new LDPepper();
        }else if ("cheese".equals(type)) {
            pizza = new LDCheese();
        }

        return pizza;
    }
  • 开始点餐。是不是主函数很简单,这就是使用设计模式的好处。
public class Test {
    public static void main(String[] args) {
        new BJStory().order();
    }
}

三、抽象工厂模式

3.1、基本介绍

  • 定义了一个interface用于创建相关或者依赖关系的对象簇,无需指明具体的类。
  • 从设计层面看,抽象工厂模式就是对简单工厂模式的更改
  • 将工厂抽象成两层,抽象工厂和具体实现的工厂子类,程序员可以根据创建对象类型使用对应的工厂子类。这样将单个工厂变成了工厂簇,更利于代码的维护和扩展。

3.2、举例演示

  • 和模式二例子一样,就不在书写了。

3.3、类图设计

在这里插入图片描述

3.4、代码展示

  • Pizza类、和其他口味的披萨类都和模式二相同,就不再写。
  • 工厂接口
public interface Factory {
    public Pizza creat(String type);
}
  • 具体工厂
public class BJFactory implements Factory {
    @Override
    public Pizza creat(String type) {
        Pizza pizza = null;

        if ("cheese".equals(type)) {
            pizza = new BJCheese();
        }else if ("pepper".equals(type)) {
            pizza = new BJPepper();
        }
        return pizza;
    }
}

public class LDFactory implements Factory {
    @Override
    public Pizza creat(String type) {
        Pizza pizza = null;

        if ("pepper".equals(type)) {
            pizza = new LDPepper();
        }else if ("cheese".equals(type)) {
            pizza = new LDCheese();
        }
        return pizza;
    }
}
  • 点餐类,另外一个LDOrder类和这个内容一样,就不再写了。或者还可以进行优化,将这些代码放进一个类里面,然后让具体的工厂再去继承,就可以节省大量的代码书写过程。
public class BJOrder {

    public void order(Factory factory) {
        String type = null;
        Pizza pizza = null;

        while (true) {
            type = getTYpe();
            pizza = factory.creat(type);

            if (null == pizza) {
                System.out.println("没有这类披萨");
                break;
            }

            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }
    }

    private String getTYpe() {
        String type = null;

        try {
            BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨种类:");
            type = bf.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return type;
    }
}
  • 开始点餐
public class Store {
    public static void main(String[] args) {
        Factory factory = new BJFactory();

        new BJOrder().order(factory);
    }
}

四、小结

4.1、 工厂模式的意义

  • 将实例化对象的代码提起出来,放到一个类中统一进行管理和维护,达到和主项目的依赖关系解耦,从而提高项目的扩展和维护性。

4.2、设计模式的依赖抽象原则

  • 创建对象实例时,不要直接new类,而是把这个new类的功能放到一个工厂的方法中去,并返回。
  • 不要让类继承具体的类,而是继承抽象或者是实现接口。
  • 不要覆盖类中已经实现的方法。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值