经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式-三种工厂模式实例
来源:cnblogs  作者:落枕的向日葵  时间:2018/9/25 20:18:59  对本文有异议

  1.简单工厂模式:代替new产生对象,产品的类型比较少时。

      我们要获得三种不同的数据库对象,如Mysql,SQLserver,Oracle,它们拥有共同的特征,即可以进行抽象,简单工厂目的是将获得具体数据库实体的任务交给工厂类。

 接口DataBase:

  1. public interface DataBase {
  2. public void open();
  3. public void close();
  4. }

 类Mysql:

  1. public class Mysql implements DataBase {
  2. @Override
  3. public void open() {
  4. System.out.println("open mysql");
  5. }
  6. @Override
  7. public void close() {
  8. System.out.println("close mysql");
  9. }
  10. }

类Oracle:

  1. public class Oracle implements DataBase {
  2. @Override
  3. public void open() {
  4. System.out.println("open Oracle");
  5. }
  6. @Override
  7. public void close() {
  8. System.out.println("close Oracle");
  9. }
  10. }

类SQLserver:

  1. public class SQLServer implements DataBase {
  2. @Override
  3. public void open() {
  4. System.out.println("open SQLServer");
  5. }
  6. @Override
  7. public void close() {
  8. System.out.println("close SQLServer");
  9. }
  10. }

 

工厂类及测试:

  1. public class Factory {
  2. public DataBase getDataBase(String Type){
  3. if(Type == null){
  4. return null;
  5. }
  6. if(Type.equalsIgnoreCase("MYSQL")){
  7. return new Mysql();
  8. } else if(Type.equalsIgnoreCase("ORACLE")){
  9. return new Oracle();
  10. } else if(Type.equalsIgnoreCase("SQLSERVER")){
  11. return new SQLServer();
  12. }
  13. return null;
  14. }
  15. @Test
  16. public void test(){
  17. Factory factory = new Factory();
  18. DataBase d1= factory.getDataBase("MYSQL");
  19. d1.open();
  20. DataBase d2= factory.getDataBase("ORACLE");
  21. d2.open();
  22. DataBase d3= factory.getDataBase("SQLSERVER");
  23. d3.open();
  24. }
  25. }

      特点: 如果要新增其他数据库,只需创建新数据库类实现功能接口,修改工厂类。

                 问题1:根据“开闭原则”:对现有功能进行拓展,但不允许修改原有代码。很明显,这时简单工厂模式需多次修改工厂类。

                 问题2:使用者实际使用时并不知道类名,他只知道有DataBase这个接口,使用这个接口就能创建对象,使用open()函数,当然实际中肯定还需传入用户名和密码等参数。

针对问题2:可以使用枚举的方式,代码如下:

  1. public class Factory2 {
  2. enum DatabaseType{
  3. MYSQL,
  4. SQLSERVER,
  5. ORACLE
  6. }
  7. public static DataBase getDataBase(DatabaseType type){
  8. switch(type){
  9. case MYSQL:
  10. return new Mysql();
  11. case ORACLE:
  12. return new Oracle();
  13. case SQLSERVER:
  14. return new SQLServer();
  15. default:
  16. throw new UnknownTypeException(null, type);
  17. }
  18. }
  19. @Test
  20. public void test(){
  21. DataBase s1=Factory2.getDataBase(DatabaseType.MYSQL);
  22. s1.open();
  23. DataBase s2=Factory2.getDataBase(DatabaseType.ORACLE);
  24. s2.open();
  25. }
  26. }

 

 2.工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。

       使用简单工厂方式使得工厂函数很难维护,而且请求者还需知道被实例化的类,而工厂方法模式可避免之。

       新建抽象工厂 IFactory,对于每个数据库都新建相应的工厂类,如MysqlFactory,OracleFactory实现 IFactory,这样在新增一种数据库时,不必修改工厂类而造成破坏封闭原则。

  1. public interface IFactory {
  2. public DataBase get();
  3. }

 

  1. class SqlFactory implements IFactory{
  2. public DataBase get(){
  3. return new Mysql();
  4. }
  5. }
  6. class OracleFactory implements IFactory{
  7. public DataBase get(){
  8. return new Oracle();
  9. }
  10. }
  11. class SQLserverFactory implements IFactory{
  12. public DataBase get(){
  13. return new SQLServer();
  14. }
  15. }
  16. //测试
  17. public class FactoryMethod{
  18. public static void main(String[] args){
  19. DataBase d1=new SqlFactory().get();
  20. d1.open();
  21. }
  22. }

       问题1:如果数据库类型越来越多,将无限的增加工厂子类,使用者同样还是需要知道工厂子类的名称。

       问题2:在使用时数据库时可能还需与其他的类相关联,工厂方法模式无法解决。

3.抽象工厂模式(Abstract Factory):提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。

      场景:若在新建数据库连接时需指定方言,而且不同数据库的SQL语言也不相同的情况下。

      组成元素:

       1.方言类和接口,如图所示:

  

      2.之前的数据库类和接口

     

      3.operFactory抽象工厂

  1. public abstract class operFactory{
  2. private IDialect dialect;
  3. abstract void add();
  4. abstract void delete();
  5. abstract void update();
  6. public void setDialect(String classname){
  7. IDialect cf=null;
  8. try {
  9. cf=(IDialect)Class.forName(classname).newInstance();
  10. setDialect(cf);
  11. } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. public IDialect getDialect() {
  16. return dialect;
  17. }
  18. public void setDialect(IDialect dialect) {
  19. this.dialect = dialect;
  20. }
  21. }

 

  4. MysqlFatory,OracleFactory( 均继承上面的抽象工厂类)

  1. public class MysqlFatory extends operFactory {
  2. @Override
  3. void add() {
  4. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  5. System.out.println("mysql add()");
  6. }
  7. @Override
  8. void delete() {
  9. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  10. System.out.println("mysql delete()");
  11. }
  12. @Override
  13. void update() {
  14. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  15. System.out.println("mysql update()");
  16. }
  17. }
  18. public class OracleFactory extends operFactory {
  19. @Override
  20. void add() {
  21. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  22. System.out.println("Oracle add()");
  23. }
  24. @Override
  25. void delete() {
  26. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  27. System.out.println("Oracle delete()");
  28. }
  29. @Override
  30. void update() {
  31. System.out.println("使用的方言为:"+this.getDialect().showDialect());
  32. System.out.println("Oracle update()");
  33. }
  34. }

 

      5.工厂构造器类 FactoryProducer 负责生成想要的数据库工厂。

  1. public class FactoryProducer {
  2. public static operFactory getFactory(String class_name) {
  3. operFactory cf=null;
  4. try {
  5. cf=(operFactory)Class.forName(class_name).newInstance();
  6. } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
  7. e.printStackTrace();
  8. }
  9. return cf;
  10. }
  11. }

 

  6.测试

  1. public static void main(String[] args){
  2. operFactory of2=FactoryProducer.getFactory(DatabaseFactoryType.MYSQL);
  3. of2.setDialect(DialectType.MySQL5InnoDBDialect);
  4. of2.update();
  5. operFactory of= FactoryProducer.getFactory(DatabaseFactoryType.ORALCE);
  6. of.setDialect(DialectType.Oracle10gDialect);
  7. of.add();
  8. }

 

 结果:

 

  总之抽象工厂总是关于创建一系列相关或相互有依赖的对象,以上例子中即DataBase对象与Dialect对象具有相关性。但是使用者要了解各种工厂和方言。

三者区别:

           简单工厂实现简单,扩展也很容易,但是会频繁修改工厂类代码,难以维护,在维护的时候容易引发新的BUG。

           工厂方法模式则是把对象的实例化延迟到了继承的子类里面,这样就变成了扩展工厂,从而满足了“开闭”原则, 但是不支持产品切换,也就是只能满足一层的产品(算法)抽象,当需与其他对象合作时无能为力。

            抽象工厂则是继续把产品进行再次抽象,最后得到一个可以支持产品切换的结构,但问题过于复杂,不过我们使用反射机制,可以弥补这个缺点,但是使用者却需要知道工厂的名称。

 

            以上工程源码分享:链接:https://pan.baidu.com/s/1ElHalIZKrr1n7391jW8uTA    密码:1ikz

          

 

  

 

      

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号