设计模式-工厂方法模式
上一篇文章 设计模式-简单工厂模式 介绍了简单工厂模式
简单工厂模式违背了”开放 – 关闭原则”,工厂类集中了所有产品(实例)的创建逻辑,违反了高内聚责任分配原则
为了解决这些问题,学习一下工厂方法模式
工厂方法模式:
工厂方法模式,又称工厂模式/多态工厂模式/虚拟构造器模式
在工厂方法模式中,定义了一个创建产品对象的接口,将实际产品(实例)的创建逻辑延迟到了接口其子类(具体工厂)当中
工厂类成为了抽象工厂角色,不再负责产品的创建
这样进一步的抽象化,使得系统在不修改具体工厂的情况下,添加新的产品
模式中包含的角色及职责:
抽象产品(Product)角色:具体产品的父类 ,用于描述产品的公共接口
具体产品(Concrete Product)角色:抽象产品的子类,工厂类创建的目标类,即产品
抽象工厂(Creator)角色:具体工厂的父类,用于描述及具体工厂的公共接口
具体工厂(Concrete Creator)角色:抽象工厂的子类,被外界调用,用于实例化具体产品对象
使用方法:
1.定义抽象产品类/定义产品公共接口
2.定义具体实现产品类
3.创建抽象工厂类
4.定义具体实现工厂类
5.外界调用具体工厂类,创建产品实例
实例:
实例代码已上传到GitLab,地址:https://gitlab.com/louisvv/DesignPattern
背景:有一个水果工厂,用来生产水果,现在有两种水果:苹果、香蕉
目的:通过工厂方法模式实现两种水果的生产
步骤如下:
1.定义抽象产品类Fruit
public abstract class Fruit { public abstract void show(); }
2.定义具体实现产品类
苹果类:
public class Apple extends Fruit { public void show(){ System.out.println("我是苹果"); } }
香蕉类:
public class Banana extends Fruit { public void show(){ System.out.println("我是香蕉"); } }
3.定义抽象工厂类
public interface FruitFactory { public Fruit getFruit(); }
4.定义具体实现工厂类
定义苹果工厂类:
public class AppleFactory implements FruitFactory{ public Fruit getFruit() { return new Apple(); } }
定义香蕉工厂类:
public class BananaFactory implements FruitFactory { public Fruit getFruit() { return new Banana(); } }
5.定义用户类,外部调用具体工厂,创建实例对象
public class User { public static void main(String[] args) { // 创建苹果工厂 FruitFactory appleFactory = new AppleFactory(); // 通过苹果工厂创建苹果实例对象 Fruit apple = appleFactory.getFruit(); apple.show(); // 创建香蕉工厂 FruitFactory bananaFactory = new BananaFactory(); // 通过香蕉工厂创建香蕉实例对象 Fruit banana = bananaFactory.getFruit(); banana.show(); } }
结果:
我是苹果 我是香蕉
现在工厂中新添了一种水果,桃子,我们需要作如下几个步骤:
1.定义具体实现产品类,即桃子类
public class Peach extends Fruit{ public void show() { System.out.println("我是桃子"); } }
2.定义具体实现工厂类,即桃子工厂类
public class PeachFactory implements FruitFactory { public Fruit getFruit() { return new Peach(); } }
3.在用户类中,新添一个桃子工厂,并通过桃子工厂创建桃子实例对象
// 创建桃子工厂 FruitFactory peachFactory = new PeachFactory(); // 通过桃子工厂创建桃子实例对象 Fruit peach = new Peach(); peach.show();
结果:
我是苹果 我是香蕉 我是桃子
至此,通过和简单工厂方法对比,我们发现,工厂方法模式,当我们新添一种水果时, 不违背“开放-关闭”原则,因为我们新添加一类水果时,不需要修改原有工厂类,而是新添加一个具体工厂
现在我们对工厂方法模式的优缺点做以总结:
优点:
1.更符合开-闭原则,扩展性高
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
简单工厂模式需要修改工厂类的判断逻辑
2.符合单一职责原则
每个具体工厂类只负责创建对应的产品
简单工厂中的工厂类存在复杂的逻辑判断
3.不使用静态工厂方法,可以形成基于继承的等级结构
简单工厂模式的工厂类使用静态工厂方法
缺点:
1.添加新产品时,除了增加新产品类外,还要增加与之对应的具体工厂类,增加了开发量;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
2.虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
3.一个具体工厂只能创建一种具体产品
适用场景:
1.对于某个产品,调用者清楚地知道应该使用哪个具体的工厂来服务,实例化该具体工厂,生产出具体的产品来;
2.只是需要一种产品,而不想知道也不需要知道工厂是如何生产出来的,只需要知道具体对应的工厂就行。
举个例子:
当我们系统需要访问外部数据源,有多种数据源选择(mysql、oracle、hdfs、mangodb等),用户不确定使用哪种数据源,或者新添了一种数据源,可以使用工厂方法模式,进行设计开发
亲,点个赞吧!
1 Response