• Java设计模式之工厂模式的两种实现方式


    工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    1. 为什么要有工厂模式?

    "Talk is cheap,show me the code". 想要找到这个问题的答案,我们先来看看下面这个项目。

    1.1  一个实体类

    public class User{
        
        public String username;
        public String password;
    }

    为了更方便讲述,我尽量让代码精简,方便我们深入了解想关注的点。

    实体类很简单,User对象,两个成员变量,username 用户名称,password 用户密码

    1.2 定义了一个IUser接口

    也很简单,只有一个insert方法

    import com.xingyun.model.User;
    
    public interface IUser {
        void insert(User user);
    }

     1.3 一个实现类IUserMySQLImpl.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class IUserMySQLImpl implements IUser{
    
        @Override
        public void insert(User user) {
            // TODO Auto-generated method stub
            System.out.println("insert to MySQL"+user.toString());
        }  
    }

    这个实现类实现了IUser接口,所以需要实现IUser接口定义的insert(User user)方法.

    1.4 最后我们可能需要再多个地方调用

    Test1.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserMySQLImpl;
    
    public class Test1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=new IUserMySQLImpl();
            test.insert(user);
        }
    }

    Test2.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserMySQLImpl;
    
    public class Test2 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=new IUserMySQLImpl();
            test.insert(user);
        }
    
    }

    我们可以发现Test1.java 和Test2.java 中调用方式都是这样:

    IUser test=new IUserMySQLImpl();
    
    test.insert(user);

     但是假设后来项目中MySQL不想用了,想换Oracle 数据库了怎么办?

    1.6 我们需要新写一个实现类 IUserOracleImpl.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class IUserOracleImpl implements IUser{
    
        @Override
        public void insert(User user) {
            // TODO Auto-generated method stub
            System.out.println("insert to Oracle"+user.toString());
        }
    
    }

    1.7 这很正常,但是我们之前有多处调用,所以我们将不得不修改Test1.java 和Test2.java,

    Test1.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserOracleImpl;
    
    public class Test1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=new IUserOracleImpl();
            test.insert(user);
        }
    }

    Test2.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserOracleImpl;
    
    public class Test2 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=new IUserOracleImpl();
            test.insert(user);
        }
    
    }

    试想下,假如Test1 ,Test 这类的调用方式有十几处的话,那么这么多地方都要改,我们是不是要累死?

    那么如何优化呢?

    2. 工厂模式手动实现方式

    聪明的大牛做了这样的优化

    2.1 实体类不变

    public class User{
        
        public String username;
        public String password;
    }

    2.2 消息接口不变

    import com.xingyun.model.User;
    
    public interface IUser {
        void insert(User user);
    }

    2.3 一个实现类IUserMySQLImpl.java

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class IUserMySQLImpl implements IUser{
    
        @Override
        public void insert(User user) {
            // TODO Auto-generated method stub
            System.out.println("insert to MySQL"+user.toString());
        }  
    }

    2.4 实现类 IUserOracleImpl.java 不变

    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class IUserOracleImpl implements IUser{
    
        @Override
        public void insert(User user) {
            // TODO Auto-generated method stub
            System.out.println("insert to Oracle"+user.toString());
        }
    
    }

    2.5 新建了一个这样的类 IUserFactory.java

    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserMySQLImpl;
    
    public class IUserFactory {
    
        public static IUser getIUserImpl() {
            return new IUserMySQLImpl();
        }
    }

    2.6 最开始调用方式改变下

    Test1.java

    import com.xingyun.factory.IUserFactory;
    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class Test1 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=IUserFactory.getIUserImpl();
            test.insert(user);
        }
    }

    Test2.java

    import com.xingyun.factory.IUserFactory;
    import com.xingyun.model.User;
    import com.xingyun.myinterface.IUser;
    
    public class Test2 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            User user=new User();
            user.username="admin";
            user.password="root";
            
            IUser test=IUserFactory.getIUserImpl();
            test.insert(user);
        }
    
    }

    然后将Test1.java和Test2.java 中原来的调用方式

    IUser test=new IUserMySQLImpl();
    test.insert(user);

    改成了这样:

    IUser test=IUserFactory.getIUserImpl();
    test.insert(user);

    于是乎,我当需要将IUserMySQLImpl更换为IUserOracleImpl 的时候,我们只需要修改这个IUserFactory即可,Test1.java和Test2.java 任何调用的地方都不再需要改变。

    import com.xingyun.myinterface.IUser;
    import com.xingyun.myinterface.impl.IUserOracleImpl;
    
    public class IUserFactory {
    
        public static IUser getIUserImpl() {
            return new IUserOracleImpl();
        }
    }

    你猜的没错,这就是Java 设计模式中著名的工厂模式,通过抽象出一个工厂,来屏蔽调用选择哪一种实现类的,这个问题丢给工厂类来处理切换哪一个实现类。

    2. 工厂模式Spring IOC实现方式

    Mark:https://www.cnblogs.com/cowboys/p/6638484.html 

    待续。。。

  • 相关阅读:
    ubuntu部分端口命令的使用----开启端口/开启防火墙
    ElasticSearch 5.0及head插件安装
    维基百科语料中的词语相似度探索
    Mac下多版本JDK安装
    Mac OS 终端利器 iTerm2
    android mat 转 bitmap
    simHash 简介以及 java 实现
    Python数据可视化之matplotlib实践 源码 第二篇 精进 第六章
    Python数据可视化之matplotlib实践 源码 第二篇 精进 第五章
    Python数据可视化之matplotlib实践 源码 第一篇 入门 第四章
  • 原文地址:https://www.cnblogs.com/xingyunblog/p/9289329.html
Copyright © 2020-2023  润新知