🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### **场景概述** 举一个店铺售卖不同品牌手机的例子:店铺,即客户端类向手机工厂购进手机售卖。 1. 最开始实例化一个商店,商店打算卖华为手机 2. 商店委托工厂给他制作一台HWPhone手机,传入对应的字段tag。 3. 手机生产好以后打包送到商店 4. 商店售卖手机 ### **场景分析** 该场景可以使用简单工厂的角色来设计: * 抽象产品:Phone,是所有具体产品类的父类,提供一个公共接口packaging表示手机的装箱并送到店铺。 * 具体产品:不同品牌的手机,小米手机类(MIPhone),华为手机类(HWPhone)。 * 工厂:PhoneFactory根据不同的参数来创建不同的手机。 * 客户端类:店铺类Store负责售卖手机。 ### **代码实现** 抽象产品类Phone: ~~~ public abstract class AbstractPhone { public abstract void packaging(); } ~~~ 具体产品类 MIPhone: ~~~ public class MIPhone extends AbstractPhone { @Override public void packaging() { System.out.println("小米手机"); } } ~~~ 具体产品类:HWPhone: ~~~ public class HWPhone extends AbstractPhone { @Override public void packaging() { System.out.println("华为手机"); } } ~~~ 以上是抽象产品类以及它的2个子类:小米手机类和华为手机类 下面看一下工厂类 PhoneFactory: ~~~ public class PhoneFactory { public IPhone createPhoneWithTag(String tag) { IPhone phone = null; switch (tag) { case "XM": phone = new MIPhone(); break; case "HW": phone = new HWPhone(); break; default: } return phone; } } ~~~ >工厂类向外部(客户端)提供了一个创造手机的接口createPhoneWithTag:,根据传入参数的不同可以返回不同的具体产品类。因此客户端只需要知道它所需要的产品所对应的参数即可获得对应的产品了。 在本例中,我们声明了店铺类 Store为客户端类: ~~~ public class Store { public void sellPhone(IPhone phone) { phone.packaging(); } } ~~~ >客户端类声明了一个售卖手机的接口sellPhone:。表示它可以售卖作为参数所传入的手机。 最后我们用代码模拟一下这个实际场景: ~~~ public static void main(String[] args) { PhoneFactory factory = new PhoneFactory(); IPhone hw = factory.createPhoneWithTag("HW"); Store store = new Store(); store.sellPhone(hw); } ~~~ 在这里我们需要注意的是:商店从工厂拿到手机不需要了解手机制作的过程,只需要知道它要工厂做的是手机(只知道IPhone类即可),和需要给工厂类传入它所需手机所对应的参数即可(这里HWPhone手机对应的参数就是tag)。 ### **代码对应的类图:** ![](https://img.kancloud.cn/df/61/df61e3b798d88b506a4ed8d2b4b761e5_763x432.png) ## **优点** * 客户端只需要给工厂类传入一个正确的(约定好的)参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合。 * 客户端无须知道所创建的具体产品类的类名,只需知道具体产品类所对应的参数即可,减少开发者的记忆成本。 ## **缺点** * 如果业务上添加新产品的话,就需要修改工厂类原有的判断逻辑,这其实是违背了开闭原则的。 * 在产品类型较多时,有可能造成工厂逻辑过于复杂。所以简单工厂模式比较适合产品种类比较少而且增多的概率很低的情况。