- 前言
- 简单实现
- 简单工厂类
- 工厂方法
- 测试案例代码
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
简单实现案例:咖啡店有两种类型的咖啡,美式咖啡和拿铁咖啡,你需要去咖啡店点咖啡。
假设,每种咖啡都需要添加牛奶和糖。
提取其中的共同点和不同点,发现:
共同点:加糖、加牛奶。
不同点:咖啡的种类。
由此,可以定义一个公共的Coffee.java类,分别记录其中的异同点。如下所示:
package factory.one;
public abstract class Coffee {
// 获取咖啡的名称
public abstract String getName();
// 加糖
public void addSugar(){
System.out.println("加糖");
}
// 加奶
public void addMilk(){
System.out.println("加奶");
}
}
咖啡有两种,则分别创建对应的类:
package factory.one;
public class AmeriacanCoffee extends Coffee {
// 返回名称
@Override
public String getName() {
return "美式咖啡";
}
}
package factory.one;
public class LetteCoffe extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
提供咖啡店,供消费者去购买。代码逻辑如下所示:
package factory.one;
// 咖啡店
public class CoffeStore {
// 根据消费者指定不同的类型,从而获取到不同类型的咖啡
public Coffee orderCoffee(String type){
Coffee coffee = null;
if("a".equals(type)){
coffee = new AmeriacanCoffee();
}else if("l".equals(type)){
coffee = new LetteCoffe();
}else{
throw new RuntimeException("没有这种类型的咖啡");
}
coffee.addSugar();
coffee.addMilk();
return coffee;
}
}
编写测试类:
package factory.one;
public class Test {
public static void main(String[] args) {
// 创建咖啡店
CoffeStore coffeStore = new CoffeStore();
// 点咖啡
//Coffee coffee = coffeStore.orderCoffee("l");
Coffee coffee = coffeStore.orderCoffee("a");
System.out.println(coffee.getName());
}
}
当消费者需要什么样的产品,只需要传递指定的类型即可。
【注意:】但如果咖啡店新增了其他类型的咖啡呢?
此时则需要改动咖啡店 CoffeeStore.java的代码逻辑。
这种新增需求,就必须改动原来业务逻辑的方式是不可取的,如何才能解决上面出现的问题呢?
简单工厂类将咖啡店中生产咖啡的逻辑单独独立出来。
为了避免因为需求的变更,导致业务逻辑中的原有逻辑需要实时更改的问题,将业务中经常需要变更的部分单独独立出来,放入一个公共的工厂中产生。
创建CoffeeFactory.java类,将CoffeeStore.java类中未来可能需要实时变更的逻辑独立出来:
public class CoffeeFactory {
public static Coffee createCoffee(String type){
Coffee coffee = null;
if("a".equals(type)){
coffee = new AmeriacanCoffee();
}else if("l".equals(type)){
coffee = new LetteCoffe();
}else{
throw new RuntimeException("没有这种类型的咖啡");
}
return coffee;
}
}
然后修改CoffeeStore.java中的逻辑。
// 咖啡店
public class CoffeStore {
public Coffee orderCoffee(String type){
// Coffee coffee = null;
// if("a".equals(type)){
// coffee = new AmeriacanCoffee();
// }else if("l".equals(type)){
// coffee = new LetteCoffe();
// }else{
// throw new RuntimeException("没有这种类型的咖啡");
// }
// 根据工厂获取对应的咖啡对象
Coffee coffee = CoffeeFactory.createCoffee(type);
coffee.addSugar();
coffee.addMilk();
return coffee;
}
}
【小结:】
这种方式,虽然解决了主体业务逻辑不会因为增加其他咖啡产品导致代码逻辑需要实时修改的问题。
即:让主体业务逻辑CoffeeStore.java与Coffee.java的子类之间解除耦合。
但是,如果有新增的其他产品,则需要实时地去修改CoffeeFactory.java中的逻辑,让CoffeeFactory.java与Coffee.java的子类之间充满耦合度。
【疑问:】如何保证既能新增产品,又能不改动代码来实现功能呢?
可以采取工厂方法模式,让子类对象的创建,交给子类工厂,至于逻辑中采取父类进行接收处理即可!
工厂方法Java的多态思想。
根据Java多态的思想,父类变量接收子类的具体实现类 Father father = new Son(),主体业务中采取父类变量接收,但逻辑处理的对象依旧还是具体实现的子类。
从之前耦合度高的代码逻辑中,可以发现:
根据不同类型,创建不同的实例化对象。
这一步骤,导致新增产品时,要使用新产品对象,则需要不断的去修改主体业务逻辑,或者工厂逻辑,导致其耦合度增高。
那么这次,则可以根据多态思想解决,代码如下所示:
咖啡的父类和其子类依旧如下:
public abstract class Coffee {
// 获取咖啡的名称
public abstract String getName();
// 加糖
public void addSugar(){
System.out.println("加糖");
}
// 加奶
public void addMilk(){
System.out.println("加奶");
}
}
public class AmeriacanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
public class LetteCoffe extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
构建子类对象产生工厂,但工厂定义父类,保证主体逻辑中以父类变量进行业务逻辑的处理。
// 抽象工厂
public interface CoffeeFactory {
// 提供创建 对应 咖啡的方法
Coffee createCoffee();
}
美式咖啡对象创建:
// 专门用于生产 美式咖啡
public class AmeCoffeeFactory implements CoffeeFactory {
@Override
public Coffee createCoffee() {
return new AmeriacanCoffee();
}
}
拿铁咖啡对象的创建:
// 专门生产 拿铁咖啡
public class LetteCoffeeFactory implements CoffeeFactory {
@Override
public Coffee createCoffee() {
return new LetteCoffe();
}
}
咖啡店中的咖啡处理,采取父类变量接收和操作,其中代码逻辑如下所示:
// 咖啡店
public class CoffeStore {
// 由各个子类工厂提供具体的实例化对象,业务逻辑中只用父类变量接收即可
private CoffeeFactory factory;
public void setFactory(CoffeeFactory factory) {
this.factory = factory;
}
public Coffee orderCoffee(){
// 父类变量调用其指定的方法。
// 多态思想:具体的实现还是需要看堆内存中具体是哪个子类,业务逻辑中不考虑
Coffee coffee = factory.createCoffee();
coffee.addSugar();
coffee.addMilk();
return coffee;
}
}
消费者进行消费:
public class Test {
public static void main(String[] args) {
CoffeStore coffeStore = new CoffeStore();
// 需要使用哪个子类的实例化对象,则直接调用其具体的实现工厂类
//CoffeeFactory factory = new AmeCoffeeFactory();
CoffeeFactory factory = new LetteCoffeeFactory();
coffeStore.setFactory(factory);
Coffee coffee = coffeStore.orderCoffee();
System.out.println(coffee.getName());
}
}
【小结:】
采取Java 多态的思想,能够将具体需要操作的实例化对象,交给消费者自己去考虑;
如果有新增的产品,比如咖啡店新增了别的咖啡种类,只需要让新增的种类具有对应的实现类CoffeeFactory.java 的子类即可。
【存在不足:】
测试案例代码每次新增一个对应Coffee的产品,都需要重新编写一个Coffee.java的具体子类,和一个CoffeeFactory.java的具体实例化工厂类。
增加了系统的复杂度。
gitee 测试代码地址



