简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。上篇文章《设计模式(二)简单工厂模式》讲了简单工厂模式,我们今天就来看一下工厂方法模式。
工厂方法模式
工厂方法模式的结构图如下所示:
AbstractFactory
:抽象工厂类,提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
Factory
:工厂类,负责实现创建所有实例的内部逻辑。创建产品类的方法可以被外界直接调用,创建所需的产品对象。
AbstractProduct
:抽象产品类,这是简单工厂模式所创建的所有对象的父类。
Product
:具体产品类,继承自抽象产品类。
下面用代码来实现一下:
- 创建抽象产品
1 2 3
| abstract class Phone { public abstract void start(); }
|
- 创建具体产品
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class OppoPhone extends Phone { @Override public void start() { System.out.println("OPPO start"); } }
class VivoPhone extends Phone { @Override public void start() { System.out.println("VIVO start"); } }
class XiaomiPhone extends Phone { @Override public void start() { System.out.println("XiaoMi start"); } }
|
- 创建抽象工厂
1 2 3
| abstract class PhoneFactory { public abstract Phone createPhone(); }
|
- 具体工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class OppoFactory extends PhoneFactory { @Override public Phone createPhone() { return new OppoPhone(); } }
class VivoFactory extends PhoneFactory { @Override public Phone createPhone() { return new VivoPhone(); } }
class XiaomiFactory extends PhoneFactory { @Override public Phone createPhone() { return new XiaomiPhone(); } }
|
- 调用工厂创建产品
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) { Phone oppoPhone = new OppoFactory().createPhone(); oppoPhone.start();
Phone vivoPhone = new VivoFactory().createPhone(); vivoPhone.start();
Phone xiaomiPhone = new XiaomiFactory().createPhone(); xiaomiPhone.start(); }
|
打印日志可以看到这种品牌的手机都启动了。至此,我们就完成了工厂方法模式的创建。
问题
由于每个具体产品对应一个具体工厂,所以会产生很多类,而且每次创建产品都需要new
一个工厂出来,对系统的性能有一定的影响。
解决
为了更好的管理工厂类,而且让工厂类可重用,我们可以创建一个工厂的工厂,使用HashMap
来对工厂进行缓存,在使用工厂时直接从HashMap
获取缓存的工厂。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class PhoneFactoryFactory {
enum PhoneType { oppo, vivo, xiaomi }
static HashMap<PhoneType, PhoneFactory> map = new HashMap<>();
static { map.put(PhoneType.oppo, new OppoFactory()); map.put(PhoneType.vivo, new VivoFactory()); map.put(PhoneType.xiaomi, new XiaomiFactory()); }
public static PhoneFactory getFactory(PhoneType type) { return map.get(type); } }
|
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) { Phone oppoPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.oppo).createPhone(); oppoPhone.start();
Phone vivoPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.vivo).createPhone(); vivoPhone.start();
Phone xiaomiPhone = PhoneFactoryFactory.getFactory(PhoneFactoryFactory.PhoneType.xiaomi).createPhone(); xiaomiPhone.start(); }
|
总结
优点:
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
- 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
缺点:
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
示例代码已上传至Github
关注我