继续整理记录这段时间来的收获,详细代码可在我的Gitee仓库Java设计模式克隆下载学习使用!
4.3 工厂模式
4.3.1 背景
- 若创建对象时直接new对象,则会使对象耦合严重,更换对象则很复杂
4.3.2 简单工厂
4.3.3 特点
- 不是一种设计模式,是编程习惯
4.3.4 结构
- 抽象产品:定义产品规范,描述产品主要功能特性
- 具体产品:实现或继承抽象产品子类
- 具体工厂:提供创建产品方法,调用通过方法来获取产品
4.3.4 特点
4.3.4.1 优点
- 将对象创建过程与业务逻辑分来,避免修改客户代码
- 降低耦合性,易于扩展
4.3.4.2缺点
- 增加新功能需要修改工厂类代码,违背“开闭原则”
4.3.5 案例(咖啡店点咖啡)
- 抽象咖啡
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 CoffeeSimpleFactory {
public Coffee createCoffeeFactory(String type)
{
Coffee coffee;
if(type.equals("American"))
coffee= new AmericanCoffee();
else if(type.equals("Latte"))
coffee= new LatteCoffee();
else throw new RuntimeException("对不起,您的咖啡本店没有!请重新点");
return coffee;
}
}
- 咖啡店
public class CoffeeStore {
public Coffee orderCoffee(String type)
{
CoffeeSimpleFactory coffeeSimpleFactory = new CoffeeSimpleFactory();
Coffee coffee = coffeeSimpleFactory.createCoffeeFactory(type);
// 加糖
coffee.addSugar();
// 加奶
coffee.addMilk();
return coffee;
}
}
- 测试
public static void main(String[] args) {
CoffeeStore coffeeStore = new CoffeeStore();
Coffee coffee = coffeeStore.orderCoffee("American");
System.out.println(coffee.getName());
}
如图
4.3.6 扩展(咖啡店点咖啡)
- 更改工厂类代码如图
- 更改咖啡店代码如图
4.3.3 工厂方法
4.3.3.1 案例
案例与简单工厂一样
4.3.3.2 结构
- 抽象工厂:提供创建产品接口,调用者通过访问具体工厂来创建产品
- 具体工厂:实现抽象工厂抽象方法,完成具体产品创建
- 抽象产品:定义产品规范,描述产品功能和特性
- 具体产品:实现抽象产品定义接口
4.3.3.3 特点
4.3.3.3.1 优点
- 用户只需知道具体工厂名称即可得到产品
- 系统增加新产品只需添加具体产品类和具体工厂类即可,无需修改原工厂
4.3.3.3.2 缺点
每增加新产品就得增加具体产品和对应具体工厂类
4.3.3.4 代码
- 其它不变
- 咖啡创建工厂接口
public interface CoffeeFactory {
public Coffee createCoffee();
}
- 美式咖啡创建工厂
public class AmericanCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
- 拿铁咖啡创建工厂
public class LatteCoffeeFactory implements CoffeeFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
}
- 咖啡店
public class CoffeeStore {
private CoffeeFactory coffeeFactory;
public void setCoffeeFactory(CoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee()
{
Coffee coffee = coffeeFactory.createCoffee();
// 加糖
coffee.addSugar();
// 加奶
coffee.addMilk();
return coffee;
}
}
- 测试,结果正确,美式咖啡
public static void main(String[] args) {
CoffeeStore coffeeStore = new CoffeeStore();
coffeeStore.setCoffeeFactory(new AmericanCoffeeFactory());
Coffee coffee = coffeeStore.orderCoffee();
System.out.println(coffee.getName());
}
- 关系图
4.3.4 抽象工厂
4.3.4.1 概念
- 工厂方法模式升级版,可生产多个等级产品
- 一种为访问类提供一个创建一组相关或相互依赖对象接口,且访问类无需指定索要产品具体类即可得到同组不同产品
4.3.4.2 结构
- 抽象工厂:提供多个创建产品接口,可创建多个不同等级产品
- 具体工厂:实现抽象工厂多个抽象方法
- 抽象产品:定义规范,描述功能
- 具体产品:实现接口,由具体工厂来创建,同具体工厂实多对一关系
4.3.4.3 特点
4.3.4.3.1 优点
当产品族中多个对象被设计一起工作时,能保证客户端始终使用同一个产品族中的对象
4.3.4.3.2 缺点
当产品族中需要增加产品时,所有工厂类均需要修改
4.3.4.4 使用场景
- 当需要创建对象是一系列相互关联或依赖产品时
- 系统有多个产品族,但每次只使用其中的某一族产品
- 系统提供产品类库,且所有产品接口相同,客户端不依赖产品实例创建细节和内部结构
4.3.4.5 案例(咖啡店)
- 咖啡与甜点抽象类
public abstract class Coffee {
public abstract String getName();
// 加糖
public void addSugar() {
System.out.println("加糖");
}
// 加奶
public void addMilk() {
System.out.println("加奶");
}
}
public abstract class Dessert {
public abstract void show();
}
- 咖啡与甜点具体产品类
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
public class Tiramisu extends Dessert{
@Override
public void show() {
System.out.println("提拉米苏");
}
}
public class MatchaMousse extends Dessert{
@Override
public void show() {
System.out.println("抹茶慕斯");
}
}
- 具体工厂类
public class AmericanDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
@Override
public Dessert createDessert() {
return new MatchaMousse();
}
}
public class ItalyDessertFactory implements DessertFactory{
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
@Override
public Dessert createDessert() {
return new Tiramisu();
}
}
- 测试类,只需要更改工厂类即可切换具体产品创建
public static void main(String[] args) {
// 创建意式风味工厂对象
// ItalyDessertFactory factory = new ItalyDessertFactory();
AmericanDessertFactory factory = new AmericanDessertFactory();
// 点拿铁咖啡
Coffee coffee = factory.createCoffee();
// 点提拉米苏
Dessert dessert = factory.createDessert();
System.out.println(coffee.getName());
dessert.show();
}
- 类图