设计模式|(一)设计模式——简单工厂,工厂方法和抽象工厂

前言 创建型模式将对象的部分创建工作延迟到子 类或者其他对象,从而应对需求变化为对象创建时具体类型实现引来的冲击。
下面将结合java代码进行对简单工厂,工厂方法和抽象工厂3种设计模型进行分析

简单工厂(simple factory) 描述:通过传入参数控制对象的生成
场景:

使用简单工厂模式设计一个可以创建不同几何形状的绘图工具,每个几何图形都要有绘制draw()和擦除erase()两个方法,要求在绘制不支持的几何图形时,提示一个UnSupportedShapeException,请根据类图编程实现该系统,并写出相应Java代码

设计模式|(一)设计模式——简单工厂,工厂方法和抽象工厂
文章图片


具体代码如下
package org.crudboy; interface Shape { void draw(); void erase(); }class Circle implements Shape { public void draw() { System.out.println("绘制圆形"); } public void erase() { System.out.println("擦除圆形"); } }class Rectangle implements Shape { public void draw() { System.out.println("绘制长方形"); } public void erase() { System.out.println("擦除长方形"); } }class Triangle implements Shape { public void draw() { System.out.println("绘制三角形"); } public void erase() { System.out.println("擦除三角形"); } }class Factory { static Shape createShape(String type) throws UnsupportedShapeException { switch (type) { case "Circle": return new Circle(); case "Rectangle": return new Rectangle(); case "Triangle": return new Triangle(); default: throw new UnsupportedShapeException(); } } }/** 自定义异常 **/ class UnsupportedShapeException extends Exception{ @Override public String toString() { return "不支持该几何图形"; } }public class SimpleFactory { public static void main(String[] args) { try { Shape shape; shape= Factory.createShape("Circle"); shape.draw(); shape.erase(); } catch(UnsupportedShapeException e) { e.printStackTrace(); } } }

可以发现,在Factory中,生成对象是通过传入的参数定死的,日后如果有新的实现类,就需要修改原代码。
这无疑违背了开发封闭原则——对扩展开发,对更改封闭。

工厂方法(factory method) 描述:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。 Factory Method使得一个类的实例化延迟(目的:解耦, 手段:虚函数)到子类。
场景:
某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式。现使用工厂方法模式设计该系统,并写出相应Java代码。

设计模式|(一)设计模式——简单工厂,工厂方法和抽象工厂
文章图片


代码如下:
package org.crudboy; interface Log { void writeLog(); }class FileLog implements Log { public void writeLog() { System.out.println("file-log"); } }class DatabaseLog implements Log { public void writeLog() { System.out.println("database-log"); } }interface LogFactory { Log createLog(); }class FileLogFactory implements LogFactory{ public Log createLog() { return new FileLog(); } }class DatabaseFactory implements LogFactory{public Log createLog() { return new DatabaseLog(); } }public class FactoryMethod {public static void main(String[] args) { LogFactory factory; Log log; factory = new FileLogFactory(); log = factory.createLog(); log.writeLog(); } }


与简单工厂相比,工厂方法对工厂也进行了抽象,当日后有新增的实现类时,只需为该实现类新增对应的实现工厂即可。
当然上述代码在创建工厂时定死了某一具体工厂,其实我们可以在配置文件中指定具体的工厂的全类名,然后通过反射技术进行加载,这样,只需要通过改变配置文件就可以控制整个对像的创建过程

抽象工厂(abstract factory) 描述:
提供一个接口,让该接口负责创建一系列“相关或者相互依 赖的对象”,无需指定它们具体的类。
如果没有应对“多系列对象构建”的需求变化,则没有必要使用 Abstract Factory模式,这时候使用简单的工厂完全可以。
“系列对象”指的是在某一特定系列下的对象之间有相互依赖、 或作用的关系。不同系列的对象之间不能相互依赖。
场景:
【设计模式|(一)设计模式——简单工厂,工厂方法和抽象工厂】某系统为了改进数据库操作的性能,自定义数据库连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象,如提供Oracle或SQL Server专用连接类和语句类,而且用户可以通过配置文件等方式根据实际需要动态更换系统数据库。使用抽象工厂模式设计该系统,并写出相应Java代码
设计模式|(一)设计模式——简单工厂,工厂方法和抽象工厂
文章图片


代码实现如下
package org.crudboy; interface Connection { void connect(); }class OracleConnection implements Connection{ public void connect() { System.out.println("Oracle connect"); } }class MySQLConnection implements Connection{ public void connect() { System.out.println("Oracle connect"); } }interface Statement{ void execute(); }class OracleStatement implements Statement{ public void execute() { System.out.println("Oracle SQL execute"); } }class MySQLStatement implements Statement{ public void execute() { System.out.println("MYSQL SQL execute"); } }interface DBFactory { Connection createConnection(); Statement createStatement(); }class OracleFactory implements DBFactory{ public Connection createConnection() { return new OracleConnection(); }public Statement createStatement() { return new OracleStatement(); } }class MySQLFactory implements DBFactory{ public Connection createConnection() { return new MySQLConnection(); }public Statement createStatement() { return new MySQLStatement(); } }public class AbstractFactory {public static void main(String[] args) { DBFactory db = new OracleFactory(); Connection con = db.createConnection(); Statement st = db.createStatement(); con.connect(); st.execute(); } }

观察抽象工厂,不难看出其与工厂方法的区别仅在于抽像工厂有多个抽象产品类 ,具体工厂类能创建多个具体产品类的对象。

    推荐阅读