我们来学习工厂模式,有的小伙伴可能会说起航篇里的大纲中没有这个模式呀,这是从哪冒出来的。事实确实如此,工厂模式包含了简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式也没有在大纲中出现,这个是较早出现的工厂模式。
大白话来说就是,当我们需要一个对象时,不需要知道具体的创建过程,只需要问工厂要即可。由此可见,工厂的作用就是为我们创建对象。
举个栗子,比如你要去买书,可能想买《Java编程思想》,也可能是《Effective Java》又或者是《深入理解Java虚拟机》,这种情况下直接去书店就能满足你的需求。这里的书店就充当工厂的作用。
简单工厂模式也叫静态工厂方法,根据传入的参数不同返回相应的对象。实现该方法所在的类就是简单工厂类。如下图所示:
这里以支付为例,日常生活中大家在付款时,用的比较多的就是支付宝和微信了。根据这个场景我们来实现简单工厂的代码。
第一步:创建支付接口
/**
* 第一步:创建抽象产品接口,定义抽象方法,让具体的产品类去实现具体业务
*/
public interface IPay {
/**
* 定义统一支付方法
*/
void unifiedorder();
}12345678910复制代码类型:[java]
第二步:创建具体的业务实现
/**
* 第二步:创建具体产品类,实现抽象产品接口,并实现具体的业务方法
*/
public class AliPay implements IPay {
@Override
public void unifiedorder() {
System.out.println("调用阿里支付");
}
}
/**
* 第二步:创建具体产品类,实现抽象产品接口,并实现具体的业务方法
*/
public class WechatPay implements IPay{
@Override
public void unifiedorder() {
System.out.println("调用微信支付");
}
}123456789101112131415161718192021复制代码类型:[java]
第三步:创建简单工厂
/**
* 第三步:创建简单工厂类,负责创建用户所需的对象
*/
public class SimplePayFactory {
/**
* 获取支付对象方法
* @param beanName
* @return
*/
public static IPay getPayInstance(String beanName) {
if (beanName.equalsIgnoreCase("AliPay")) {
return new AliPay();
} else if (beanName.equalsIgnoreCase("WechatPay")) {
return new WechatPay();
} else {
return null;
}
}
}1234567891011121314151617181920复制代码类型:[java]
第四步:测试
public class SimpleFactoryTest {
public static void main(String[] args) {
IPay aliPay = SimplePayFactory.getPayInstance("AliPay");
aliPay.unifiedorder();
IPay wechatPay = SimplePayFactory.getPayInstance("WechatPay");
wechatPay.unifiedorder();
}
}123456789复制代码类型:[java]
运行结果:
调用阿里支付
调用微信支付12复制代码类型:[java]
优点:解耦
缺点:
违背开闭原则,新增Product类需要修改 getPayInstance 代码
一定程度上增加了类的数量
不利于系统的维护和扩展
工厂方法模式又称工厂模式,是简单工厂的一个变种,解决了开闭原则问题。用户只需要知道具体工厂的名称就可以拿到相应的对象。如下图所示:
还是以支付为例,在工厂方法中,原有内容保持不变,但多了一层获取具体工厂的接口。
第一步:创建支付接口
**
* 第一步:创建抽象产品接口,定义抽象方法,让具体的产品类去实现具体业务
*/
public interface IPay {
/**
* 定义统一支付方法
*/
void unifiedorder();
}12345678910复制代码类型:[java]
第二步:创建具体的业务实现
/**
* 第二步:创建具体产品类,实现抽象产品接口,并实现具体的业务方法
*/
public class AliPay implements IPay {
@Override
public void unifiedorder() {
System.out.println("调用阿里支付");
}
}
/**
* 第二步:创建具体产品类,实现抽象产品接口,并实现具体的业务方法
*/
public class WechatPay implements IPay{
@Override
public void unifiedorder() {
System.out.println("调用微信支付");
}
}123456789101112131415161718192021复制代码类型:[java]
第三步:创建获取支付对象的工厂
/**
* 第三步:抽象工厂类,用于描述具体工厂的公共接口
*/
public interface IPayFactory {
/**
* 具体工厂的抽象方法
* @return IPay
*/
IPay getPay();
}1234567891011复制代码类型:[java]
第四步:创建具体工厂类
/**
* 第四步:具体工厂类,实现抽象工厂接口,完成对象创建
*/
public class AlipayFactory implements IPayFactory{
@Override
public IPay getPay() {
return new AliPay();
}
}
/**
* 第四步:具体工厂类,实现抽象工厂接口,完成对象创建
*/
public class WechatFactory implements IPayFactory{
@Override
public IPay getPay() {
return new WechatPay();
}
}123456789101112131415161718192021复制代码类型:[java]
第五步:测试
public class MethodFactoryTest {
public static void main(String[] args) {
IPayFactory alipayFactory = new AlipayFactory();
IPay aliPay = alipayFactory.getPay();
aliPay.unifiedorder();
IPayFactory wechatFactory = new WechatFactory();
IPay wechatPay = wechatFactory.getPay();
wechatPay.unifiedorder();
}
}
123456789101112复制代码类型:[java]
运行结果:
调用阿里支付
调用微信支付12复制代码类型:[java]
优点:
解耦
符合开闭原则
提高了扩展性和复用性
缺点:
类数量过多,工厂越多复杂性越高
更具抽象性,增加了理解成本
抽象产品接口只能生产一种产品
通过工厂方法的学习,大家也可以感觉到该模式只考虑同类型的产品,但是生活中同样有很多综合型的工厂,如大学有很多的专业,企业里有很多的岗位等等,这就造就了抽象工厂模式。
为了更好的理解抽象工厂,我们先来了解下产品的相关概念,如下图所示:
简单工厂模式不建议在产品种类多的情况下使用
接下来就以苹果和华为公司生产电脑和手机为例,实现抽象工厂。如下图所示:
第一步:创建产品工厂
/**
* 第一步:创建电脑工厂,并定义功能
*/
public interface IComputerFactory {
/**
* 开机
*/
void start();
/**
* 关机
*/
void stop();
}
/**
* 第一步:创建手机工厂,并定义功能
*/
public interface IPhoneFactory {
/**
* 开机
*/
void start();
/**
* 关机
*/
void stop();
}12345678910111213141516171819202122232425262728293031复制代码类型:[java]
第二步:创建具体产品
创建苹果产品:
/**
* 第二步:创建具体产品(苹果电脑)
*/
public class Mac implements IComputerFactory{
@Override
public void start() {
System.out.println("苹果电脑开机");
}
@Override
public void stop() {
System.out.println("苹果电脑关机");
}
}
/**
* 第二步:创建具体产品(苹果手机)
*/
public class IPhone implements IPhoneFactory{
@Override
public void start() {
System.out.println("苹果手机开机");
}
@Override
public void stop() {
System.out.println("苹果手机关机");
}
}123456789101112131415161718192021222324252627282930复制代码类型:[java]
创建华为产品:
/**
* 第二步:创建具体产品(华为电脑)
*/
public class HuaWeiComputer implements IComputerFactory{
@Override
public void start() {
System.out.println("华为电脑开机");
}
@Override
public void stop() {
System.out.println("华为电脑关机");
}
}
/**
* 第二步:创建具体产品(华为手机)
*/
public class HuaWeiPhone implements IPhoneFactory{
@Override
public void start() {
System.out.println("华为手机开机");
}
@Override
public void stop() {
System.out.println("华为手机关机");
}
}123456789101112131415161718192021222324252627282930复制代码类型:[java]
第三步:创建企业工厂
/**
* 第三步:创建企业工厂(苹果工厂)
*/
public class AppleFactory implements IProductFactory{
@Override
public IPhoneFactory phoneProduct() {
return new IPhone();
}
@Override
public IComputerFactory computerProduct() {
return new Mac();
}
}
/**
* 第三步:创建企业工厂(华为工厂)
*/
public class HuaWeiFactory implements IProductFactory{
@Override
public IPhoneFactory phoneProduct() {
return new HuaWeiPhone();
}
@Override
public IComputerFactory computerProduct() {
return new HuaWeiComputer();
}
}12345678910111213141516171819202122232425262728293031复制代码类型:[java]
第四步:创建最上层抽象工厂
/**
* 第四步:创建最上层抽象工厂
*/
public interface IProductFactory {
/**
* 生产手机
* @return IPhoneFactory
*/
IPhoneFactory phoneProduct();
/**
* 生产电脑
* @return IComputerFactory
*/
IComputerFactory computerProduct();
}1234567891011121314151617复制代码类型:[java]
第五步:抽象工厂测试
public class AbstractFactoryTest {
public static void main(String[] args) {
// 苹果产品系列
IProductFactory appleFactory = new AppleFactory();
IComputerFactory appleComputerFactory = appleFactory.computerProduct();
appleComputerFactory.start();
appleComputerFactory.stop();
IPhoneFactory applePhoneFactory = appleFactory.phoneProduct();
applePhoneFactory.start();
applePhoneFactory.stop();
System.out.println("======================");
// 华为产品系列
IProductFactory huaWeiFactory = new HuaWeiFactory();
IComputerFactory huaWeiComputerFactory = huaWeiFactory.computerProduct();
huaWeiComputerFactory.start();
huaWeiComputerFactory.stop();
IPhoneFactory huaWeiPhoneFactory = huaWeiFactory.phoneProduct();
huaWeiPhoneFactory.start();
huaWeiPhoneFactory.stop();
}
}12345678910111213141516171819202122复制代码类型:[java]
运行结果:
苹果电脑开机
苹果电脑关机
苹果手机开机
苹果手机关机
====分割线====
华为电脑开机
华为电脑关机
华为手机开机
华为手机关机123456789复制代码类型:[java]
优点:工厂方法的扩展,实现了产品族生产。
缺点:
不是很符合开闭原则
产品族扩展困难
比工厂方法更抽象,理解更困难
通过本篇文章的学习,总结以下几点:
简单工厂模式不建议在产品种类多的情况下使用
工厂方法模式适用于多种厂家生产类似产品,项目中使用频率较低
抽象工厂是工厂方法的扩展,实现了产品族生产
抽象工厂在实际开发中的出现的频率更低
抽象工厂中每个工厂只生产一个产品时建议使用工厂方法
是工厂方法的扩展,实现了产品族生产
抽象工厂在实际开发中的出现的频率更低
抽象工厂中每个工厂只生产一个产品时建议使用工厂方法
随着科学技术的发展,人们对生活质量的追求不断提高,无线智能家居越来越容易被人们接受和应用,越来越多的电动窗帘产品进入人们的生活。 随之,也产生了如果电动窗帘维护不当,容易引起电动窗帘故障的问题。 现在,让我们来看看无线智能家居的自控窗帘应该如何维护。电动窗帘开关不好,或者中途不能靠近。 由于手动或其
屋面出现漏水的问题,对日常的生活也会带来极大的影响,但屋面却经常会有漏水的问题,屋面漏水的原因有哪些?面对屋面有漏水的问题,及时快速的解决才是关键,如不解决后果也会特别的严重,来看看屋面漏水的解决办法有哪些。一、屋面漏水的原因有哪些?1、现浇板渗漏原因有两点:现浇板内预埋接线盒上浮,使雨水直接从接线