Java设计模式 | 简单工厂模式

在这里插入图片描述

概述

需求

设计一个咖啡店点餐系统
设计一个咖啡类(Coffee);并定义其两个子类(美式咖啡AmericanCoffee和拿铁咖啡LatteCoffee);再设计一个咖啡店类(CoffeeStore),其具备点咖啡的功能。

类图

image.png

咖啡类
public abstract class Coffee {

    // 获取咖啡名
    public abstract String getName();

    // 加糖
    public void addSugar(){
        System.out.println("加糖");
    }

    // 加奶
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类
public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}

拿铁咖啡类
public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

咖啡店类
public class CoffeeStore {

    public Coffee orderCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        // 加糖和奶
        coffee.addSugar();
        coffee.addMilk();

        return coffee;
    }
}
测试
public class Client {
    public static void main(String[] args) {
        // 1 创建咖啡店类
        CoffeeStore coffeeStore = new CoffeeStore();

        // 2 点咖啡
        Coffee coffee = coffeeStore.orderCoffee("Latte");
        System.out.println(coffee.getName());
    }
}

在Java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new,就会对该对象耦合严重,假如需要更换对象,所有new的地方都需要修改一遍,这显然违背了开闭原则。如果使用工厂来生产对象,就只需要和工厂打交道就好了,彻底和对象解耦,如果需要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的。所以说,工厂模式的最大优点就是:解耦

三种工厂:

  • 简单工厂模式(不属于GOF的23种经典设计模式)
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂不是一种设计模式,反而比较像是一种编程习惯。

结构

简单工厂包含以下角色:

  • 抽象产品:定义了产品的规范,描述了产品的主要特征和功能(通用行为)
  • 具体产品:实现或继承抽象产品(接口/抽象类)的子类
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品(根据传递的不同参数来创建不同的产品示例)
实现

image.png
咖啡类:

public abstract class Coffee {

    // 获取咖啡名
    public abstract String getName();

    // 加糖
    public void addSugar(){
        System.out.println("加糖");
    }

    // 加奶
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类:

public class AmericanCoffee extends Coffee {
    @Override
    public String getName() {
        return "美式咖啡";
    }
}

拿铁咖啡类:

public class LatteCoffee extends Coffee {
    @Override
    public String getName() {
        return "拿铁咖啡";
    }
}

简单咖啡工厂类:

public class SimpleCoffeeFactory {
    public Coffee createCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        return coffee;
    }
}

咖啡店类:

public class CoffeeStore {

    public Coffee orderCoffee(String type) {

        // 实例化工厂
        SimpleCoffeeFactory simpleCoffeeFactory = new SimpleCoffeeFactory();

        // 调用生产咖啡的方法
        Coffee coffee = simpleCoffeeFactory.createCoffee(type);

        // 加糖和奶
        coffee.addSugar();
        coffee.addMilk();

        return coffee;
    }
}

测试:

public class Cilent {
    public static void main(String[] args) {
        // 创建咖啡店类对象
        CoffeeStore coffeeStore = new CoffeeStore();

        // 点咖啡
        Coffee coffee = coffeeStore.orderCoffee("Latte");
        System.out.println(coffee.getName());
    }
}

总结

工厂(factory)处理创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期如果需要Coffee对象直接从工厂中获取即可。这样就解除了CoffeeStore和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore和SimpleCoffeeFactory的耦合,工厂对象和商品对象的耦合。
后期如果需要增加新咖啡,势必需要修改SimpleCoffeeFactory的代码,违反了开闭原则。工厂的客户端可能有很多,如创建美团外卖等,这样只需要修改工厂类的代码,省去了其他的操作。

简单工厂简化了客户端操作,客户端可以调用工厂方法来获取具体的产品,而无需直接与具体产品类交互,降低了耦合,但是有一个很大的问题就是不够灵活,如果需要添加新产品,就需要修改工厂类的代码。

优点:

  • 封装了创建对象的过程,可以通过参数直接获取对象
  • 把对象的创建和业务逻辑层分开,避免了修改客户端的代码,如果要实现新产品直接修改工厂类,不需要在原代码中修改,降低客户代码修改的可能性,更容易扩展

缺点:

  • 增加新产品时需要修改工厂类的代码,违背了开闭原则

扩展(静态工厂)

在实际开发中,一部分开发人员将工厂类中创建对象的功能定义成静态的,这就是静态工厂模式,也不属于23种设计模式,是一种编程习惯。
好处就是客户端可以不用实例化工厂对象,直接调用即可。

public class SimpleCoffeeFactory {
    public static Coffee createCoffee(String type) {
        // 根据类型创建咖啡实例
        Coffee coffee = null;
        if("Latte".equals(type)) {
            coffee = new LatteCoffee();
        }
        else if("Americano".equals(type)) {
            coffee = new AmericanCoffee();
        }
        else {
            System.out.println("Sorry, we don't have this kind of coffee.");
        }

        return coffee;
    }
}
  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值