- 简单工厂的扩展
静态工厂:
在开发过程中: 一部分人将工厂类创建对象的功能定义为静态的,这个就是静态工厂模式,也不是23种设计模式之一。
将这个方法更改成: 静态方法
package com.jsxs.pattern.factory.Single_Factory; /** * @Author Jsxs * @Date 2023/4/17 13:56 * @PackageName:com.jsxs.pattern.factory.Single_Factory * @ClassName: SimleCoffeeFactory * @Description: TODO 简单工厂 * @Version 1.0 */ public class SimpleCoffeeFactory { public static Coffee createCoffee(String type){ Coffee coffee=null; if ("american".equals(type)){ coffee=new AmericanCoffee(); // 1. 创建一个美食咖啡 }else if ("latte".equals(type)){ coffee=new LatteCoffee(); //2. 创建一个拿铁咖啡 }else { throw new RuntimeException("对不起,你点的咖啡没有"); } return coffee; } }
利用类名去创建对象
package com.jsxs.pattern.factory.Single_Factory; /** * @Author Jsxs * @Date 2023/4/17 13:55 * @PackageName:com.jsxs.pattern.factory.Single_Factory * @ClassName: CoffeeStore * @Description: TODO * @Version 1.0 */ public class CoffeeStore { // 1.创建点餐业务 public Coffee orderCoffee(String type) { // 2.具体商品我们去工厂获取 Coffee coffee = SimpleCoffeeFactory.createCoffee(type); // 3.加配料 coffee.addMilk(); coffee.addSuger(); return coffee; } }
(3).工厂方法模式
针对上面的优缺点: 使用工厂方法模式就可以完美的解决,完全遵循开闭原则。
定义一个用于创建对象的接口,让子类决定实列化哪个产品对象。工厂方法使一个产品类的实列化延迟到了其他工厂的子类。
- 结构
工厂方法模式的主要角色
- 抽象工厂:
提供一个创建产品的接口
,调用者通过它访问具体工厂的工厂方法来创建产品。 - 具体工厂: 主要是实现抽象工厂的抽象方法,完成具体产品的创建
- 抽象产品:
定义了产品的规范
,描述了产品的主要特性和功能。 - 具体产品:
实现了产品所定义的接口
,由具体的工厂来创建,它同具体工厂之间一一对应。
- 实现
抽象产品
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 13:54 * @PackageName:com.jsxs.pattern.factory.Single_Factory * @ClassName: Coffee * @Description: TODO * @Version 1.0 */ public abstract class Coffee { // 0. 子类必须要实现抽象方法 public abstract String getName(); // 1.加糖 public void addSuger() { System.out.println("加糖"); } // 2.加奶 public void addMilk() { System.out.println("加奶"); } }
具体产品
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs`在这里插入代码片` * @Date 2023/4/17 12:51 * @PackageName:com.jsxs.pattern.factory.before * @ClassName: LatteCoffe * @Description: TODO 拿铁咖啡 * @Version 1.0 */ public class LatteCoffee extends Coffee { @Override public String getName() { return "拿铁咖啡"; } }
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 12:50 * @PackageName:com.jsxs.pattern.factory.before * @ClassName: AmericanCoffee * @Description: TODO 美式咖啡 * @Version 1.0 */ public class AmericanCoffee extends Coffee { @Override public String getName() { return "美式咖啡"; } }
抽象工厂
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 14:52 * @PackageName:com.jsxs.pattern.factory.factory_method * @ClassName: CoffeeFactory * @Description: TODO 工厂接口 * @Version 1.0 */ public interface CoffeeFactory { Coffee createCoffee(); }
具体工厂
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 14:53 * @PackageName:com.jsxs.pattern.factory.factory_method * @ClassName: AmericanCoffeeFactoryImp * @Description: TODO 实现美式咖啡 * @Version 1.0 */ public class AmericanCoffeeFactoryImp implements CoffeeFactory{ @Override public Coffee createCoffee() { return new AmericanCoffee(); } }
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 14:54 * @PackageName:com.jsxs.pattern.factory.factory_method * @ClassName: LatteCoffeeFactoryImp * @Description: TODO 拿铁咖啡实现 * @Version 1.0 */ public class LatteCoffeeFactoryImp implements CoffeeFactory{ @Override public Coffee createCoffee() { return new LatteCoffee(); } }
咖啡商店
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 14:50 * @PackageName:com.jsxs.pattern.factory.factory_method * @ClassName: CoffeeStore * @Description: TODO 咖啡店 * @Version 1.0 */ public class CoffeeStore { private CoffeeFactory coffeeFactory; public void setCoffeeFactory(CoffeeFactory coffeeFactory) { this.coffeeFactory = coffeeFactory; } // 点咖啡的功能 public Coffee orderCoffee() { Coffee coffee = coffeeFactory.createCoffee(); coffee.addMilk(); coffee.addSuger(); return coffee; } }
测试类
package com.jsxs.pattern.factory.factory_method; /** * @Author Jsxs * @Date 2023/4/17 14:57 * @PackageName:com.jsxs.pattern.factory.factory_method * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) { CoffeeStore coffeeStore = new CoffeeStore(); // 点一杯美式咖啡 coffeeStore.setCoffeeFactory(new AmericanCoffeeFactoryImp()); // 订餐... Coffee coffee = coffeeStore.orderCoffee(); System.out.println(coffee.getName()); } }
- 优缺点
优点:
- 用户只需要知道具体工厂的名称就可以得到所要的产品,无须知道产品的具体创建过程。
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂,无需对原工厂进行任何修改,满足开闭原则。
缺点:
- 每增加一个产品就需要
增加一个具体产品类和一个对应的具体工厂
,增加了系统的复杂性。
4.抽象工厂模式 (咖啡-套餐)
前面介绍的工厂方法模式考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视。
这些工厂只生产同种类产品,同种类产品称为同等级产品.也就是说:“工厂方法模式只考虑生产同等级的产品,凡是现实生活中许多工厂是综合性的工厂,能生产多等级(种类)的产品,如电器厂及生产电视又生产洗衣机或空调,大学既有软件专业也有生物专业等。”
本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族。下图所示X轴是产品等级,也就是同一类产品(华为手机 苹果手机)。Y轴是产品族,也就是同一品牌的不同产品(华为手机 华为电脑),同一品牌的产品产自同一个工厂。
(1).概述
抽象工厂模式:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所需产品的具体类
就能得到同族的不同等级的产品模式结构
。
抽象工厂模式是 工厂方法模式的升级版本,工厂方法模式只生产同一个等级的产品,而抽象工厂模式可以生产多个等级的产品。
(2).结构
抽象工厂模式的主要角色:
- 抽象工厂:
提供一个创建产品的接口
,它包含了多个创建产品的方法,可以创建多个不同等级的产品 - 具体工厂: 主要是
实现抽象工厂中的多个抽象方法
,完成具体产品的创建 - 抽象产品:
定义了产品的规范
,描述了产品的主要特性和功能。 - 具体产品:
实现了产品所定义的接口
,由具体的工厂来创建,它同具体工厂之间一一对应。
(3).实现
现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点,如提拉米苏、抹茶慕斯
等,钥匙按照工厂方法模式,需要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸。其中拿铁咖啡、没事咖啡是一个产品等级
,都是咖啡;提拉米苏、抹茶慕斯
是一个产品等级;拿铁咖啡和提拉米苏
是同一产族(都是意大利风格),美式咖啡和抹茶慕斯
是同一产族(美式风格)。
抽象咖啡
package com.jsxs.pattern.factory.abstract_factory; /** * @Author Jsxs * @Date 2023/4/17 12:47 * @PackageName:com.jsxs.pattern.factory.before * @ClassName: Coffe * @Description: TODO 咖啡类 * @Version 1.0 */ public abstract class Coffee { // 0. 子类必须要实现抽象方法 public abstract String getName(); // 1.加糖 public void addSuger() { System.out.println("加糖"); } // 2.加奶 public void addMilk() { System.out.println("加奶"); } }
抽象甜品
package com.jsxs.pattern.factory.abstract_factory; /** * @Author Jsxs * @Date 2023/4/17 16:20 * @PackageName:com.jsxs.pattern.factory.abstract_factory * @ClassName: Dessert * @Description: TODO 甜品-抽象类 * @Version 1.0 */ public abstract class Dessert { public abstract void show(); }