• 设计模式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的问题。如果使用配置文件的话,可以彻底不用修改代码,而达到更换数据库的问题。

          


  • 相关阅读:
    nodeclub 学习记录
    读mongoose api 记录
    sublime 插件 和free 注册码
    mongodb 基本语法
    安装 adobe flash player
    nginx 安装
    压缩 解压文件
    async 异步流程控制规则
    a标签# 和javascript:;的区别
    获取url 参数
  • 原文地址:https://www.cnblogs.com/deman/p/4125965.html
Copyright © 2020-2023  润新知