本篇我们来学习工厂模式,有的小伙伴可能会说起航篇里的大纲中没有这个模式呀,这是从哪冒出来的。事实确实如此,工厂模式包含了简单工厂模式、工厂方法模式和抽象工厂模式。 简单工厂模式也没有在大纲中出现,这个是较早出现的工厂模式。 什么是工厂模式大白话来说就是,当我们需要一个对象时,不需要知道具体的创建过程,只需要问工厂要即可。由此可见,工厂的作用就是为我们创建对象。 举个栗子,比如你要去买书,可能想买《Java编程思想》,也可能是《Effective Java》又或者是《深入理解Java虚拟机》,这种情况下直接去书店就能满足你的需求。这里的书店就充当工厂的作用。 简单工厂(Simple Factory)简单工厂模式也叫静态工厂方法,根据传入的参数不同返回相应的对象。实现该方法所在的类就是简单工厂类。如下图所示: 这里以支付为例,日常生活中大家在付款时,用的比较多的就是支付宝和微信了。根据这个场景我们来实现简单工厂的代码。 第一步:创建支付接口 /** * 第一步:创建抽象产品接口,定义抽象方法,让具体的产品类去实现具体业务 */ 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 代码 一定程度上增加了类的数量 不利于系统的维护和扩展 工厂方法(Factory Method)工厂方法模式又称工厂模式,是简单工厂的一个变种,解决了开闭原则问题。用户只需要知道具体工厂的名称就可以拿到相应的对象。如下图所示: 还是以支付为例,在工厂方法中,原有内容保持不变,但多了一层获取具体工厂的接口。 第一步:创建支付接口 ** * 第一步:创建抽象产品接口,定义抽象方法,让具体的产品类去实现具体业务 */ 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] 优点: 解耦 符合开闭原则 提高了扩展性和复用性 缺点: 类数量过多,工厂越多复杂性越高 更具抽象性,增加了理解成本 抽象产品接口只能生产一种产品 抽象工厂(Abstract Factory)通过工厂方法的学习,大家也可以感觉到该模式只考虑同类型的产品,但是生活中同样有很多综合型的工厂,如大学有很多的专业,企业里有很多的岗位等等,这就造就了抽象工厂模式。 为了更好的理解抽象工厂,我们先来了解下产品的相关概念,如下图所示: 简单工厂模式不建议在产品种类多的情况下使用 接下来就以苹果和华为公司生产电脑和手机为例,实现抽象工厂。如下图所示: 第一步:创建产品工厂 /** * 第一步:创建电脑工厂,并定义功能 */ 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] 优点:工厂方法的扩展,实现了产品族生产。 缺点: 不是很符合开闭原则 产品族扩展困难 比工厂方法更抽象,理解更困难 总结通过本篇文章的学习,总结以下几点: 简单工厂模式不建议在产品种类多的情况下使用 工厂方法模式适用于多种厂家生产类似产品,项目中使用频率较低 抽象工厂是工厂方法的扩展,实现了产品族生产 抽象工厂在实际开发中的出现的频率更低 抽象工厂中每个工厂只生产一个产品时建议使用工厂方法 是工厂方法的扩展,实现了产品族生产 抽象工厂在实际开发中的出现的频率更低 抽象工厂中每个工厂只生产一个产品时建议使用工厂方法 |
|