简单工厂模式
基本流程:
1、首先需要创建各种不同的对像的相关代码封装到不同的类中
这些类称为具体的产品类,将它们公共的代码进行抽象和提取封装在一个抽象产品类中
每一个具体的产品类都是抽象产品的子类
2、提供一个工厂类用于创建各种产品,在工厂类中提供一个创建容器的方法
该方法可以根据传入的参数不同创建不同的具体产品对象
客户端只需要调用工厂类的方法并传入响应的参数即可得到一个产品对象
定义:
定义一个工厂类,它可以根据参数的不同返回不同类的
实例,被创建的实例通常都具有共同的父类。
因为在简单工厂模式中用于创建实例的方法是
静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属
于类创建型模式。
要点:
当需要什么时,只需要传入一个正确的参数
就可以获取想要的对象
无需知道细节
图示:
角色:
Factory(工厂角色):
工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产
品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了
静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product。
class Factory { //静态工厂方法 public static Product getProduct(String arg) { Product product = null; if (arg.equalsIgnoreCase("A")) { product = new ConcreteProductA(); //初始化设置product } else if (arg.equalsIgnoreCase("B")) { product = new ConcreteProductB(); //初始化设置product } return product; } }
Product(抽象产品角色):
它是工厂类所创建的所有对象的父类,封装了各种产品对象的
公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,
因为所有创建的具体产品对象都是其子类对象。
abstract class Product { //所有产品类的公共业务方法 public void methodSame() { //公共方法的实现 } //声明抽象业务方法 public abstract void methodDiff(); }
ConcereProduct(具体的产品角色):
它是简单工厂模式的创建目标,所有被创建的对象都充
当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在
抽象产品中声明的抽象方法。
class ConcreteProduct extends Product { //实现业务方法 public void methodDiff() { //业务方法的实现 } }
在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用new关键字
来创建对象,它是工厂模式家族中最简单的一员。
使用简单工厂模式时:
1、需要对产品进行重构,不能设计一个包罗万象的产品类
2、根据实际情况设计一个产品层次结构,将所有产品类公共的代码移至抽象产品类
并在抽象产品类中声明一些抽象方法,以供不同的具体产品类实现
事例:
假设此时定义一个类用于将所有的图标代码封装在一个Chart类中
class Chart { private String type; //图表类型 public Chart(Object[][] data, String type) { this.type = type; if (type.equalsIgnoreCase("histogram")) { //初始化柱状图 } else if (type.equalsIgnoreCase("pie")) { //初始化饼状图 } else if (type.equalsIgnoreCase("line")) { //初始化折线图 } } public void display() { if (this.type.equalsIgnoreCase("histogram")) { //显示柱状图 } else if (this.type.equalsIgnoreCase("pie")) { //显示饼状图 } else if (this.type.equalsIgnoreCase("line")) { //显示折线图 } } }
客户端代码通过调用Chart类的构造函数来创建图表对象
根据参数type的不同可以得到不同类型的图表,然后再调用display()方法来显示相应的图表。
存在的问题:
1、整个类的代码相当冗长,代码越长阅读、维护、测试的难度很大,存在的添加语句会影响系统性能
2、该类的职责过于繁重,违反了单一职责原则,不利于维护
3、添加新的类型图标时,还需要进行修改源代码,违背了开闭原则
4、只能通过new关键字来创建对象,耦合度较高
5、每次创建对象都需要进行大量的代码重复
解决方案:
抽象的产品类
//抽象产品类 public interface Chart { public void display(); }
具体的产品类:
//具体的产品类 public class HistogramChart implements Chart { public HistogramChart(){ System.out.println("创建HistogramChart对象!!"); } @Override public void display() { System.out.println("显示柱状图!!!"); } }
//具体的产品类 public class LineChart implements Chart{ public LineChart(){ System.out.println("创建LineChart对象!!"); } @Override public void display() { System.out.println("显示折线图!!"); } }
//具体的产品类 public class PieChart implements Chart{ public PieChart(){ System.out.println("创建PieChart对象!!"); } @Override public void display() { System.out.println("显示饼图!!"); } }
工厂角色
//工厂类 public class ChartFactory { public static Chart getChart(String type){ Chart chart = null; if (type.equalsIgnoreCase("histogram")){ chart = new HistogramChart(); }else if (type.equalsIgnoreCase("pie")){ chart = new PieChart(); }else if (type.equalsIgnoreCase("line")){ chart = new LineChart(); } return chart; } }
客户端的调用测试:
public class client{ public static void main(String[] args) { Chart chart; chart = ChartFactory.getChart("pie"); chart.display(); } }
此时需要什么对象即可进行创建出所需要的对象
不需要知道其中的细节
此时的结构图:
优点:
(1) 工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以
免除直接创建产品对象的职责,而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。
(2) 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,
对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量。
(3) 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,
在一定程度上提高了系统的灵活性。
缺点:
(1) 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受
到影响。
(2) 使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂
度和理解难度。
(3) 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成
工厂逻辑过于复杂,不利于系统的扩展和维护。
(4) 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
适用场景:
(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太
过复杂。
(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心