zoukankan      html  css  js  c++  java
  • 设计模式3---抽象工厂模式

    public interface IFactory {
        IUser CreateUser();
        IDepartment CreateDepartment();
    }

    在工厂模式中,每个工厂类会为特定的操作类型产生操作对象类。

    但是如果有产品系列的话,工厂模式就不太适用。

    考虑一个数据库的问题。

    1.数据库可能有替换

    2.每个数据库可以修改多个表,比如user,department。

    抽象工厂类就是对于工厂类产生的对象,我其实不需要得到具体的类,只要抽象类(接口)就可以了。

    main方法:

    public class AbstractFactoryMain extends BasicExample {
    
        @Override
        public void startDemo() {
            // TODO Auto-generated method stub
            User user = new User();
            Department department = new Department();
            IFactory factory = new AccessFactory();
            IUser iu = factory.CreateUser();
            iu.insertUser(user);
            iu.getUser(1);
            
            IDepartment id = factory.CreateDepartment();
            id.insertDepartment(department);
            id.getDepartment(1);
        }
    
    }
    IFactory 是工厂方法接口
    IUser 和IDepartment 是对于User和Department的操作接口,具体是access还是SQLserver其实客户端不关心。

    其他类具体实现:
    public interface IFactory {
        IUser CreateUser();
        IDepartment CreateDepartment();
    }
    
    
    //封装对User表的操作
    public interface IUser {
        void insertUser(User user);
        User getUser(int id);
    }
    //封装对Department表的操作
    public interface IDepartment {
        void insertDepartment(Department department);
        Department getDepartment(int id);
    }

    SQLserver工厂类:

    public class SqlServerFactory implements IFactory {
    
        @Override
        public IUser CreateUser() {
            // TODO Auto-generated method stub
            return new SqlserverUser();
        }
    
        @Override
        public IDepartment CreateDepartment() {
            // TODO Auto-generated method stub
            return new SqlserverDepartment();
        }
    
    }

    Access工厂类:

    public class AccessFactory implements IFactory {
    
        @Override
        public IUser CreateUser() {
            // TODO Auto-generated method stub
            return new AccessUser();
        }
    
        @Override
        public IDepartment CreateDepartment() {
            // TODO Auto-generated method stub
            return new AccessDepartment();
        }
    
    }

    具体操作类:

    
    
    public class SqlserverUser implements IUser {
    
        @Override
        public void insertUser(User user) {
            System.out.println("在SQLserver 中给user表添加一条记录");
        }
    
        @Override
        public User getUser(int id) {
            System.out.println("在SQLserver 中根据ID得到user表一条记录");
            return null;
        }
    
    }
    
    
    public class SqlserverDepartment implements IDepartment {
    
        @Override
        public void insertDepartment(Department department) {
            System.out.println("在SQLserver 中给Department表添加一条记录");
        }
    
        @Override
        public Department getDepartment(int id) {
            System.out.println("在SQLserver 中根据ID得到Department表一条记录");
            return null;
        }
    
    }
    
    
    public class AccessDepartment implements IDepartment {
    
        @Override
        public void insertDepartment(Department department) {
            // TODO Auto-generated method stub
            System.out.println("在Access 中给Department表添加一条记录");
        }
    
        @Override
        public Department getDepartment(int id) {
            System.out.println("在Access 中根据ID得到Department表一条记录");
            return null;
        }
    
    }
    
    
    public class AccessUser implements IUser {
    
        @Override
        public void insertUser(User user) {
            System.out.println("在Access 中给user表添加一条记录");
        }
    
        @Override
        public User getUser(int id) {
            System.out.println("在Access 中根据ID得到user表一条记录");
            return null;
        }
    
    }
    public class User {
        
        private int _id;
        private String _name;
    
        
        public int getID() {
            return _id;
        }
        public void setID(int _id) {
            this._id = _id;
        }
        public String getName() {
            return _name;
        }
        public void setName(String _name) {
            this._name = _name;
        }
        
    }
    public class Department {
        private int _id;
        private String _name;
    
        
        public int getID() {
            return _id;
        }
        public void setID(int _id) {
            this._id = _id;
        }
        public String getName() {
            return _name;
        }
        public void setName(String _name) {
            this._name = _name;
        }
    }
    如果需要添加Oracle 数据库,那只要添加 工厂生成类OracleFactory,以及操作OracleUser 和OracleDepartment类。
    这样就不会改动原有代码,可以快速替换数据库。
    抽象工厂模型:
    优点: 1.可以方便的交换产品系列,只需在初始化的地方出现一次,就可以应用一个具体工厂。  
        2.具体实现隔离客户端,客户端通过抽象接口来操作具体实例。

    简单工厂模型优化抽象工厂模型。
    把AccessFactory 和SqlserverFactory可以合并成DataAccess方法来处理。

    问题:如果上述“ IFactory factory = new AccessFactory();” 有还多处地方,甚至好几百处,这样就需要做大量的修改。
    AccessFactory用DataAccess来代替,客户端彻底杜绝出现数据库字段。
    public class DataAccess {
    //    private static final String db = "Sqlserver";
        private static final String db = "Access";
        
        public static IUser CreateUser()
        {
            IUser result = null;
            switch(db)
            {
            case "Sqlserver":
                result = new SqlserverUser();
                break;
            case "Access":
                result = new AccessUser();
                break;
            }
            return result;
        }
        
        public static IDepartment CreateDepartment()
        {
            IDepartment result = null;
            switch(db)
            {
            case "Sqlserver":
                result = new SqlserverDepartment();
                break;
            case "Access":
                result = new AccessDepartment();
                break;
            }
            return result;
        }
    }
    
    

    main方法修改为:

    public class AbstractFactoryMain extends BasicExample {
    
        @Override
        public void startDemo() {
            // TODO Auto-generated method stub
            User user = new User();
            Department department = new Department();
    //        IFactory factory = new AccessFactory();
            IUser iu = DataAccess.CreateUser();
            iu.insertUser(user);
            iu.getUser(1);
            
            IDepartment id = DataAccess.CreateDepartment();
            id.insertDepartment(department);
            id.getDepartment(1);
        }
    
    }

      从main方法看,根本看不到任何SQL和Access的字段,也就是客户端与业务逻辑隔离了!

      但是,如果新增一个Oracle数据库,需要修改DataAccess的switch--case,如何彻底不用switch语句呢?

    利用反射,把类对象反射出来,这样只需要添加工厂类定义就可以了。
    package com.jayfulmath.designpattern.abstractfactory;
    
    import java.lang.reflect.*;
    public class DataAccessReflection {
    
        private static final String AssemblyName = "com.jayfulmath.designpattern.abstractfactory";
        private static final String db = "Access";
        
        public static IUser CreateUser()
        {
            String className =AssemblyName+"."+db+"User";
            IUser  result = null;
            try {
                Class<?> c = Class.forName(className);
                Constructor<?> ct = c.getConstructor();
                result = (IUser) (ct.newInstance());
            } catch (NoSuchMethodException |ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            return result;
        }
        
        public static IDepartment CreateDepartment()
        {
            String className = AssemblyName+"."+db+"Department";
            IDepartment  result = null;
            try {
                Class<?> c = Class.forName(className);
                Constructor<?> ct = c.getConstructor();
                result = (IDepartment) (ct.newInstance());
            } catch (NoSuchMethodException |ClassNotFoundException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            return result;
        }
    }
    
    

    自此,完美的解决了switch---case的问题。如果使用配置文件的话,可以彻底不用修改代码,而达到更换数据库的问题。

          


  • 相关阅读:
    streamsets 集成 cratedb 测试
    streamsets k8s 部署试用
    streamsets rest api 转换 graphql
    StreamSets sdc rpc 测试
    StreamSets 相关文章
    StreamSets 多线程 Pipelines
    StreamSets SDC RPC Pipelines说明
    StreamSets 管理 SDC Edge上的pipeline
    StreamSets 部署 Pipelines 到 SDC Edge
    StreamSets 设计Edge pipeline
  • 原文地址:https://www.cnblogs.com/deman/p/4125965.html
Copyright © 2011-2022 走看看