工厂模式:关于一个工厂的故事

本文通过一个生产电视机的工厂故事,阐述了工厂模式在软件设计中的运用,从简单工厂模式到工厂方法模式的演变,强调了设计模式的灵活性和可扩展性,以及如何遵循开闭原则、迪米特法则、依赖倒置原则和里氏代换原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于一个工厂的故事

话说有一个生产电视机的工厂,可以生产海信电视机、海尔电视机。程序设计如下:

/**
 * 电视机工厂
 * @author zherop
 */
public class TVFactory {
	/**
	 * 生产海尔电视机
	 *
	 * @return
	 */
	public HaierTV createHaierTV() {
		return new HaierTV();
	}

	/**
	 * 生产海信电视机
	 *
	 * @return
	 */
	public HisenseTV createHisenseTV() {
		return new HisenseTV();
	}
}

/**
 * 海尔电视机
 * @author zherop
 */
public class HaierTV {
	public void play() {
		System.out.println("海尔电视机播放...");
	}
}

/**
 * 海信电视机
 * @author zherop
 */
public class HisenseTV {
	public void play() {
		System.out.println("海信电视机播放...");
	}
}

一切都是那么美好,随着工厂业务的发展,现在又需要生产华为电视机。这个时候,厂长找到工程师小曾,让他给出个设计方案。

于是小曾稍作思考,并想到如下方案:
新增 HuaweiTV,然后修改 TVFactory

/**
 * 华为电视机
 * @author zherop
 */
public class HuaweiTV {
	public void play() {
		System.out.println("华为电视机播放...");
	}
}

public class TVFactory {
	/**
	 * 生产华为电视机
	 * @return
	 */
	public HuaweiTV createHuaweiTV() {
		return new HuaweiTV();
	}
}

咋一看,这么设计还挺自然的。小曾又想了想,似乎不太对,新增了一个品牌的电视机,就需要去整改一直运作良好的工厂,心想,万一整改的过程中,不小心影响了其他产品线咋办?

于是,小曾陷入沉思,电视机要定一个标准,然后针对这个标准,工厂产品线就可以生产出来,于是乎,方案变成了这样:
电视机标准:

public interface TV {
	public void play();
}

所有品牌电视机都遵循这个标准:

/**
 * 海尔电视机
 * @author zherop
 */
public class HaierTV implements TV {
	public void play() {
		System.out.println("海尔电视机播放...");
	}
}

/**
 * 海信电视机
 * @author zherop
 */
public class HisenseTV implements TV {
	public void play() {
		System.out.println("海信电视机播放...");
	}
}

/**
 * 华为电视机
 * @author zherop
 */
public class HuaweiTV implements TV {
	public void play() {
		System.out.println("华为电视机播放...");
	}
}

工厂产品线改造:

/**
 * 电视机工厂
 * @author zherop
 */
public class TVFactory {
	/**
	 * 生产电视机
	 *
	 * @return
	 */
	public <T extends TV> TV createTV(Class<T> tv) {
		try {
			return tv.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("生产过程中发生故障!");
		}
		return null;
	}
}

工厂生产测试:

public class Client {
	public static void main(String[] args) {
		TVFactory tvFactory = new TVFactory();
		// 生产海尔电视机
		TV tv = tvFactory.createTV(HaierTV.class);
		// 测试电视机是否正常工作
		tv.play();
	}
}

这样,即使以后再接其他品牌的单,工厂也不用改造了。小曾顿时心情愉悦,很有成就感。
就这样,靠着这个万能的产品线,工厂稳步发展…

随着科技的进步,开始出现了新型的电视机——智慧屏。智慧屏的生产比普通电视机要复杂得多,工厂现在的设计已经不能满足需求了,厂长又开始着急了,不接这个单?那显示是不可能,如果不更新换代,工厂迟早会淘汰。于是厂长又找到了小曾。

小曾思考了下,很自然地想到了把生成电视机的产品线改造下:

/**
 * 电视机工厂
 * @author zherop
 */
public class TVFactory {
	/**
	 * 生产电视机
	 * 
	 * @return
	 */
	public <T extends TV> TV createTV(Class<T> tv) {
		try {
			T product = tv.newInstance();
            // 如果是智慧屏,特殊加工处理
			if (tv.getSimpleName().equals("HonorSmartTV")) {
				processSmartTV(product);
			}
			return product;
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("生产过程中发生故障!");
		}
		return null;
	}

	private void processSmartTV(TV product) {
		System.out.println("智慧屏加工!");
	}
}

/**
 * 荣耀智慧屏
 * @author zherop
 */
public class HonorSmartTV implements TV {

	public void play() {
		System.out.println("荣耀智慧屏播放...");
	}
}

小曾又想了想,咋又要动现有的产品线?不得行,不得行!现在虽然轻松,以后要是再出现其他新型电视机,又要改动,老是改来改去,迟早要出事!

经过一番苦想,既然电视生产的具体流程没法统一,何不建造新的工厂,由特定的工厂来针对性地生产特定的电视机呢?又想到了如下方案:

要建立多个工厂,那么就需要有工厂的标准,工厂是用来生产电视机,而不是来干其他事情的。

电视机工厂建设标准:

/**
 * 电视机工厂
 * @author zherop
 */
public interface TVFactory {
	/**
	 * 生产电视机
	 * 
	 * @return
	 */
	public TV createTV();
}

建造具体工厂:

/**
 * 海尔电视机工厂
 * @author zherop
 */
public class HaierTVFacatory implements TVFactory {

	public TV createTV() {
		return new HaierTV();
	}
}

/**
 * 海信电视机工厂
 * @author zherop
 */
public class HisenseTVFactory implements TVFactory {

	public TV createTV() {
		return new HisenseTV();
	}

}

/**
 * 荣耀智慧屏工厂
 * @author zherop
 */
public class HonorSmartTVFactory implements TVFactory {

	public TV createTV() {
		return new HonorSmartTV();
	}

}

测试:

public class Client {
	public static void main(String[] args) {
		// 使用荣耀智慧屏工厂
		TVFactory tvFactory = new HonorSmartTVFactory();
		TV tv = tvFactory.createTV();
		// 测试电视机是否正常工作
		tv.play();
	}
}

嘿嘿,小曾心想,这样工厂以后灵活性很高了,无论科技怎么发展,工厂都能轻松应对。

看到这儿,故事就差不多结束了,至此工厂方法模式也讲得差不多了,各种变体也蕴含其中。设计模式虽是招式,但是需要根据不同的场景,进行灵活变动,不能太死板了。

定义

工厂方法模式定义:工厂方法模式又称工厂模式,工厂父类负责定义创建产品对象的公共接口,而工程子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

涉及的角色:

  1. 抽象产品(Product)
    抽象产品是定义产品的接口。比如故事中的TV类。

  2. 具体产品(ConcreteProduct)
    具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间一一对应。比如故事中的HisenseTV、HonorSmartTV、HaierTV类。

  3. 抽象工厂(Factory)
    在抽象工厂类中,声明了工厂方法,用于返回一个产品。比如故事中的TVFactory类。

  4. 具体工厂(ConcreteFactory)
    具体工厂类是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实现。比如故事中的HisenseTVFactory、HonorSmartTVFactory类。

类图:
工厂模式类图
工厂方法模式,扩展性非常好,符合开闭原则,是典型的解耦框架。高层模块只需要知道产品的抽象类,其他实现类都不需要关心,符合迪米特法则;只依赖于产品类的抽象,符合依赖倒置原则;也符合里氏代换原则。

理论上,工厂方法模式在所有需要生成对象的地方都可以使用,但是需要考虑是否要增加一个工厂类来进行管理,毕竟会增加代码的复杂度。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值