网站首页 > 数据库 / 正文
一、简单工厂
简单工厂其实不是一个设计模式,反而比较像一种编程习惯
1.1 定义
简单工厂又叫静态工厂方法,它提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
1.2 使用场景
- 1.工厂类负责创建的对象比较少
- 2.客户端(应用层)只知道出传入工厂类的参数,而对于如何创建对象(逻辑)不关心
1.3 优点&缺点
优点
只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
缺点
工厂类的职责相对国过重,增加新的产品,需要修改工厂类的判断逻辑,违背开闭原则
1.4 代码演示
比如,上一篇文章中,OrderService类,使用到持久层MySqlDao、SqlServerDao。我们创建一个简单的持久层工厂。
public interface AbstractDao { /** * 插入订单 */ void insertOrder(); } public class SqlServerDao implements AbstractDao{ @Override public void insertOrder() { System.out.println("通过SqlServer插入数据"); } } public class MySqlDao implements AbstractDao { @Override public void insertOrder() { System.out.println("通过MySql插入数据"); } }
public class DaoFactory { public static AbstractDao createDao(String type) { if ("mysql".equals(type)) { return new MySqlDao(); } else if ("sqlserver".equals(type)) { return new SqlServerDao(); } return null; } }
系统内如果需要加入Oracle数据,这时候还是需要修改DaoFactory,这样违背了设计模式的开闭原则。修改下代码。如下:
public static AbstractDao createDao(Class className) { AbstractDao abstractDao = null; try { abstractDao = (AbstractDao) Class.forName(className.getName()).newInstance(); } catch (Exception ex) { ex.printStackTrace(); } return abstractDao; }
1.6 java源码中简单工厂的应用
Calendar类的中createCalendar方法中
... if (cal == null) { // If no known calendar type is explicitly specified, // perform the traditional way to create a Calendar: // create a BuddhistCalendar for th_TH locale, // a JapaneseImperialCalendar for ja_JP_JP locale, or // a GregorianCalendar for any other locales. // NOTE: The language, country and variant strings are interned. if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") { cal = new BuddhistCalendar(zone, aLocale); } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") { cal = new JapaneseImperialCalendar(zone, aLocale); } else { cal = new GregorianCalendar(zone, aLocale); } } ...
1.7 小结
简单工厂命名建议:类名称建议为“模块名称+Factory”。方法名通常为“get+接口名称”或者“create+接口名称”。
简单工厂的方法其实就是==选择==一个合适的实现类来使用,不是真正创建的。
由于客户端在调用工厂的时候传入了选择的参数,这就说明客户端必须知道每个参数的意义,也需要理解每个参数对应的功能处理。这就要求必须在一定程度上,向客户端暴露一定的内部实现细节。
二、工厂方法
工厂方法指的是作为工厂的方法
2.1 定义
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
2.2 适用场景
- 1.创建对象需要大量重复的代码
- 2.客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 3.一个类通过其子类来指定创建哪个对象
2.3 优点&缺点
优点
用户只需要关心所需产品对应的工厂,无须关心创建细节。加入新的产品符合开闭原则,提高可扩展性。
缺点
类的个数容易过多,增加复杂度。增加了系统的抽象性和理解难度。
2.4 代码示范
继续上面的代码,原本DaoFactory负责了所有具体类的实例化。通过工厂方法,将DaoFactory定义成抽象或者接口,由其子类来决定实例化哪个。这样就将类的实例化推迟到子类。
public abstract class DaoFactory { public abstract AbstractDao createDao(); } public class MysqlDaoFactory extends DaoFactory{ @Override public AbstractDao createDao() { return new MySqlDao(); } } public class SqlServerDaoFactory extends DaoFactory { @Override public AbstractDao createDao() { return new SqlServerDao(); } }
测试
public class OrderServerTests { public static void main(String[] args) { AbstractDao dao = new MysqlDaoFactory().createDao(); OrderService orderService=new OrderService(); orderService.setDao(dao); orderService.insertOrder(); } }
如果这时候需要增加Oracle数据库,这时候就增加OracleDaoFactory就行。
public class OracleDao implements AbstractDao { @Override public void insertOrder() { System.out.println("使用Oracle插入数据"); } }
public class OracleDaoFactory extends DaoFactory { @Override public AbstractDao createDao() { return new OracleDao(); } }
客户端只需要修改AbstractDao的实例指向OracleDaoFactory
public class OrderServerTests { public static void main(String[] args) { AbstractDao dao = new OracleDaoFactory().createDao(); OrderService orderService=new OrderService(); orderService.setDao(dao); orderService.insertOrder(); } }
2.5 简单工厂与工厂方法的区别
简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端而言,去除了与具体产品的依赖。但是对于新增其他逻辑,则需要修改工厂类。从而违背了开闭原则。
工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要加功能,本来就改工厂类的,而现在是修改客户端。
三、抽象工厂
3.1 定义
抽象工厂模式提供了一个创建==一系列==相关或者相互依赖对象的接口。无须指定它们具体的类型
3.2 使用场景
- 1.客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 2.强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
- 3.提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现
3.3 优点&缺点
优点
具体产品在应用层代码隔离,无须关心创建细节。将一个系列的产品族统一到一起创建
缺点
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
增加了系统的抽象性和理解难度
3.4 代码示范
同样使用上面的MySql、SqlServer持久层代码示例。原先我们在AbstractDao只定义了insertOrder方法,而实际的业务代码中,还有其他的数据库操作的方法,比如删除订单、更新订单、查询订单一系列操作。我们并不关心具体的比如插入订单方法,而关心整个持久层的所有的方法。
public interface InsertOrder { void insertOrder(); } public interface QueryOrder { void queryOrder(); } public class MySqlInsertOrder implements InsertOrder { @Override public void insertOrder() { System.out.println("使用Mysql插入订单"); } } public class MySqlQueryOrder implements QueryOrder { @Override public void queryOrder() { System.out.println("使用Mysql查询订单"); } } public class SqlServerInsertOrder implements InsertOrder { @Override public void insertOrder() { System.out.println("使用SqlServer插入订单"); } } public class SqlServerQueryOrder implements QueryOrder { @Override public void queryOrder() { System.out.println("使用sqlServer查询订单"); } }
抽象工厂
public abstract class DaoFactory { public abstract InsertOrder getInsertOrder(); public abstract QueryOrder getQueryOrder(); } public class MysqlDaoFactory extends DaoFactory { @Override public InsertOrder getInsertOrder() { return new MySqlInsertOrder(); } @Override public QueryOrder getQueryOrder() { return new MySqlQueryOrder(); } } public class SqlServerDaoFactory extends DaoFactory { @Override public InsertOrder getInsertOrder() { return new SqlServerInsertOrder(); } @Override public QueryOrder getQueryOrder() { return new SqlServerQueryOrder(); } }
测试
public class Test { public static void main(String[] args) { DaoFactory daoFactory = new MysqlDaoFactory(); InsertOrder insertOrder = daoFactory.getInsertOrder(); QueryOrder queryOrder = daoFactory.getQueryOrder(); insertOrder.insertOrder(); queryOrder.queryOrder(); } }
3.5 工厂方法与抽象工厂区别
工厂方法模式一般是针对单独的产品对象创建,而抽象工厂模式注重产品簇对象的创建,这就是它们之间的区别。如果产品簇只有一个产品,这时候抽象方法跟工厂方法是差不多的。
Tags:oracle insert as
猜你喜欢
- 2024-11-26 ORACLE RAC数据库的挂起分析
- 2024-11-26 oracle-高水位
- 2024-11-26 Oracle ROWID详解及其妙用
- 2024-11-26 Mybatis标签使用
- 2024-11-26 oracle Merge Into 用法
- 2024-11-26 oracle创建触发器-1
- 2024-11-26 常用SQL系列之(五):多表和禁止插入、批量与特殊更新等
- 2024-11-26 Oracle数据定义
- 2024-11-26 Oracle定时任务
- 2024-11-26 Oracle数据库性能调优实践(三)——账号及密码管理