《设计模式奇妙之旅》第2章 工厂方法模式

第2章 工厂方法模式

2.1 关于工厂方法模式

工厂模式在Java种是比较常用的一种创建型设计模式。
工厂模式创建对象时对外界暴露接口隐藏创建对象的细节。

2.2 我们来举个例子

说起了工厂,我们第一想到的是,肯定是造东西用的吧。
现在有一个食物售卖机,有热狗、汉堡包、炸鸡腿三种快餐供选择。 现有老八前来买它想念依旧的食物。
用户只需要知道有什么,点击自己想要的把信息告诉机器,
机器则给我们调配出我们所要的东西。而我们只需知道这样调用、
不需要知道在售卖机内部到底发生了什么。
抽象类(食物) 个体类(热狗、汉堡包、炸鸡腿) 工厂(售卖机) 客户端(顾客)

2.3 我们先来试着编写代码吧

  • 类图
    在这里插入图片描述

  • Food.java

public abstract class Food {
    protected String name;
    protected float price;
    public String getName(){
        return name;
    }
    public float getPrice(){
        return price;
    }
}
  • FriedChicken.java
public class FriedChicken extends Food {
    public FriedChicken(){
        this.name="炸鸡腿";
        this.price=4.3f;
    }
}
  • Hamburger.java
public class Hamburger extends Food {
    public Hamburger(){
        this.name="汉堡包";
        this.price=3.3f;
    }
}
  • HotDog.java
public class HotDog extends Food {
    public HotDog(){
        this.name="热狗";
        this.price=2.3f;
    }
}
  • Main.java
public class Main {
    public static void out(Food[] foods){
        for(int i=0;i<foods.length;i++){
            System.out.println(String.format("名称 %s 价格 %f",foods[i].getName(),foods[i].getPrice()));
        }
    }
    public static void main(String[] args) {
        //现在有一个顾客购买汉堡包、炸鸡
        Food hotDog=new HotDog();
        Food friedChicken=new FriedChicken();
        out(new Food[]{hotDog,friedChicken});
    }
}
  • 运行结果
    名称 热狗 价格 2.300000
    名称 炸鸡腿 价格 4.300000

可见我们的顾客直接与各个实体类打交道,我们并没有在创建实体类时隐藏细节。

2.4 进行改进

  • 在Main客户与各种食物之间放置工厂,客户使用工厂,工厂负责调度创建哪些实体。

  • 类图
    在这里插入图片描述

  • Main.java

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void out(Food[] foods){
        for(int i=0;i<foods.length;i++){
            System.out.println(String.format("名称 %s 价格 %f",foods[i].getName(),foods[i].getPrice()));
        }
    }
    public static void main(String[] args) {
        //创建工厂
        FoodFactory foodFactory=new FoodFactoryImpl();
        //现在有一个顾客购买汉堡包、炸鸡
        Food hotDog=foodFactory.getFood("汉堡包");
        Food friedChicken=foodFactory.getFood("炸鸡腿");
        out(new Food[]{hotDog,friedChicken});
        //批量生产
        List<String> names=new ArrayList<>();
        names.add("汉堡包");names.add("炸鸡腿");names.add("热狗");names.add("热狗");
        List<Food> foods=foodFactory.getFoods(names);
        System.out.println("批量生产");
        for(Food food:foods){
            System.out.println(String.format("名称 %s 价格 %f",food.getName(),food.getPrice()));
        }
    }
}
  • Food.java
public abstract class Food {
    protected String name;
    protected float price;
    public void setName(String name){
        this.name=name;
    }
    public void setPrice(float price){
        this.price=price;
    }
    public String getName(){
        return name;
    }
    public float getPrice(){
        return price;
    }
}
  • FriedChicken.java
public class FriedChicken extends Food {
    public FriedChicken(float price){
        setName("炸鸡腿");
        setPrice(price);
    }
}
  • Hamburger.java
public class Hamburger extends Food {
    public Hamburger(float price){
        setName("汉堡包");
        setPrice(price);
    }
}
  • HotDog.java
public class HotDog extends Food {
    public HotDog(float price){
        setName("热狗");
        setPrice(price);
    }
}
  • FoodFactory.java
import java.util.*;

public interface FoodFactory {
    public Food getFood(String name);
    public List<Food> getFoods(List<String> names);
}
  • FoodFactoryImpl.java
import java.util.ArrayList;
import java.util.List;

public class FoodFactoryImpl implements FoodFactory{
    private final float hamburgerPrice=2.3f;
    private final float hotdogPrice=3.4f;
    private final float friedChickenPrice=4.3f;
    @Override
    public Food getFood(String name) {
        Food food=null;
        if(name.equals("汉堡包")){
            food=new Hamburger(hamburgerPrice);
        }else if(name.equals("炸鸡腿")){
            food=new FriedChicken(friedChickenPrice);
        }else if(name.equals("热狗")){
            food=new FriedChicken(hotdogPrice);
        }
        return food;
    }

    @Override
    public List<Food> getFoods(List<String> names) {
        List<Food> foods=new ArrayList<>();
        for(int i=0;i<names.size();i++){
            foods.add(getFood(names.get(i)));
        }
        return foods;
    }
}
  • 运行结果

名称 汉堡包 价格 2.300000
名称 炸鸡腿 价格 4.300000
批量生产
名称 汉堡包 价格 2.300000
名称 炸鸡腿 价格 4.300000
名称 炸鸡腿 价格 3.400000
名称 炸鸡腿 价格 3.400000

可见、我们解耦了各种食物类与Main,Main不再需要直接创建食物对象,而是由工厂来进行,
大部分的细节我们隐藏到了工厂内部。可以看见,
我们把各种食物的价格设置功能提到了抽象类里面,而且当我们修改价格时,
直接去工厂类里面修改就好了。我们增加一些食物时,
我们也能很快的有规律的对我们的程序添加内容。

2.5 总结

当在不同情况下实例化不同的对象时,我们建立工厂接口提供外界服务。
工厂实例内部提供创建这些对象的细节,工厂返回的是抽象类的子类。
避免了用户与所创建的大量类的创建交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高万禄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值