• 简单工厂、工厂方法 、抽象工厂模式之间的联系


    概念

    1.简单工厂: 简单工厂模式中工厂为具体工厂,产品为抽象产品,由工厂实例创建产品实例。
    2.工厂方法模式: 定义一个用于创建对象的接口,让其子类确定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
    3.抽象工厂模式: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    1.简单工厂案例及解析

    类图:
    在这里插入图片描述
    这是一个简单工厂的类图,我们可以从一个案例中来对它进行讲解:
    比如小明突发奇想,想做一个关于计算器的编程代码,小明第一次编写代码时,将所有的代码都写在一个类里面,而且只有加减乘除四种方法。
    从上述的描述中,我们不难看出,如果我们在添加一个功能的话,那么只能在本类中进行更改,在多添加十个功能,那么最后可能只有自己才能看懂。所以,我们使用简单工厂来进行改进。

    代码:

    运算类

    public class Operation {
        private double numberA=0;
        private double numberB=0;
    
        public double getNumberA() {
            return numberA;
        }
    
        public void setNumberA(double numberA) {
            this.numberA = numberA;
        }
    
        public double getNumberB() {
            return numberB;
        }
    
        public void setNumberB(double numberB) {
            this.numberB = numberB;
        }
    
        public  double GetResult(){
            double result = 0;
            return result;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    其他具体逻辑类

    public class OperationAdd extends Operation{
    
        @Override
        public double GetResult(){
            double result = 0;
            result=getNumberA()+getNumberB();
            return result;
        }
    }
    
    
    
    public class OperationSub extends Operation{
    
        @Override
        public double GetResult(){
            double result = 0;
            result=getNumberA()-getNumberB();
            return result;
        }
    }
    
    
    
    public class OperationMul extends Operation{
    
        @Override
        public double GetResult(){
            double result = 0;
            result=getNumberA()*getNumberB();
            return result;
        }
    }
    
    
    
    public class OperationDiv extends Operation{
    
        @Override
        public double GetResult(){
            double result = 0;
            if (getNumberB()==0) {
                System.out.println("除数不能为零!");
    
            }else {
                result=getNumberA()/getNumberB();
            }
    
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    简单运算工厂类

    public class OperationFactory {
        public static Operation createOperate(String operate){
            Operation oper=new Operation();
            switch (operate){
                case "+":
                    oper=new OperationAdd();
                    break;
                case "-":
                    oper=new OperationSub();
                    break;
                case "*":
                    oper=new OperationMul();
                    break;
                case "/":
                    oper=new OperationDiv();
                    break;
            }
            return oper;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    客户端代码

    public class Text {
        public static void main(String[] args) {
            Operation op=OperationFactory.createOperate("+");
            op.setNumberA(1);
            op.setNumberB(2);
            double result = op.GetResult();
            System.out.println(result);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    实现

    3.0
    
    • 1

    总结:
    在简单工厂里面,客户端操作人员,不需要知道具体的逻辑,只要进行数字的输入和运算的字符输入,即可知道最后的答案。而且我们在修改其中的某一个具体的类时,也不会影响到其他的类。

    特点:使用静态的方法通过接收参数的不同来返回不同的实例。

    缺点:当我们添加新的开跟或者平方等其他运算时,就违反了开放-封闭原则。

    优点:灵活性高。在工厂类中包含了必要的逻辑,根据客户端的条件动态的实例化相关的类,对客户端来说,去掉了与产品的具体依赖。

    2.工厂方法案例及解析

    类图:
    在这里插入图片描述
    解析:
    不难看出,工厂方法是简单工厂的迭代升级,现在是由具体的工厂来进行每个类的实例化。

    我们在这里再看一个案例,小明的同学小红,继承了雷锋精神。经常到一个老人家中帮忙,近几天,小红得了病不能再去帮助老人了,就委托了小明和社区的志愿者去老人家中帮忙。

    代码:

    雷锋类:

    public class LeiFeng {
        public void Sweep(){
            System.out.println("扫地");
        }
    
        public void Wash(){
            System.out.println("洗衣");
        }
    
        public void BuyRice(){
            System.out.println("买米");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    学生和社区志愿者继承雷锋类:

    public class Undergraduate extends LeiFeng{
    
    }
    
    public class Volunteer extends LeiFeng {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    雷锋工厂

    public interface IFactory {
        LeiFeng CreateLeiFeng();
    }
    
    
    • 1
    • 2
    • 3
    • 4

    继承雷锋精神的人

    学生工厂:

    public class UndergraduateFactory implements IFactory {
        @Override
        public LeiFeng CreateLeiFeng() {
            return new Undergraduate();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    社区志愿者工厂:

    public class VolunteerFactory implements IFactory {
        @Override
        public LeiFeng CreateLeiFeng() {
                return new Volunteer();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    客户端代码:

    public class Test {
        public static void main(String[] args) {
            IFactory factory=new UndergraduateFactory();
            LeiFeng student=factory.CreateLeiFeng();
    
            student.Sweep();
            student.BuyRice();
            student.Wash();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    实现:

    扫地
    买米
    洗衣
    
    • 1
    • 2
    • 3

    总结:
    工厂方法针对每一个继承雷锋类的人提供一个工厂类,如果我们还要添加其他继承雷锋精神的人,那么直接添加类即可。

    缺点:不易于维护,假如某个具体类要进行修改,很可能需要修改对应的工厂类。当同时修改多处代码时,对工厂类的修改就会变得相当的麻烦。

    优点:创建对象的接口,让子类去决定具体实例化的对象,把内部逻辑判断转移到客户端代码。工厂方法克服了简单工厂违背开放-封闭原则的缺点,不用每次新增新类型产品都修改工厂类,又保持了封装对象创建过程的优点。

    3.抽象工厂案例及解析

    类图:
    在这里插入图片描述
    案例:
    这天,小明在工作时遇到一个项目,项目的要求是:客户现在希望自己的数据可以从两种数据库的存取数据,并且现在有两张表,每个表都有一个添加和查询的方法。

    那么我们怎么实现具体的代码呢?

    IUser接口

    public interface IUser {
        void Insert(User user);
        User GetUser(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    public interface IDepartment {
        void Insert(Department department);
        User GetUser(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    public interface IFactory {
        IUser CreateUser();
        IDepartment CreateDepartment();
    }
    
    • 1
    • 2
    • 3
    • 4

    Sqlserver数据库对应操作所创建的类

    public class SqlserverUser implements IUser {
        @Override
        public void Insert(User user) {
            System.out.println("在SQL server中给user表增加一条记录");
        }
    
        @Override
        public User GetUser(int id) {
            System.out.println("在SQL server中根据ID得到user表一条记录");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class SqlserverDepartment implements IDepartment {
        @Override
        public void Insert(Department department) {
            System.out.println("在SQL server中给Department表增加一条记录");
        }
    
        @Override
        public User GetUser(int id) {
            System.out.println("在SQL server中根据ID得到Department表一条记录");
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    public class SqlServerFactory implements IFactory {
        @Override
        public IUser CreateUser() {
            return new SqlserverUser();
        }
    
        @Override
        public IDepartment CreateDepartment() {
            return new SqlserverDepartment();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    从这里开始就是 Access数据库对应操作所创建的类

    public class AccessUser implements IUser{
        @Override
        public void Insert(User user) {
            System.out.println("在Access中给user表增加一条记录");
        }
    
        @Override
        public User GetUser(int id) {
            System.out.println("在Access中根据ID得到user表一条记录");
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class AccesssDepartment implements IDepartment {
        @Override
        public void Insert(Department department) {
            System.out.println("在Access中给Department表增加一条记录");
        }
    
        @Override
        public User GetUser(int id) {
            System.out.println("在Access中根据ID得到Department表一条记录");
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    public class AccessFactory implements IFactory {
        @Override
        public IUser CreateUser() {
            return new AccessUser();
        }
    
        @Override
        public IDepartment CreateDepartment() {
            return new AccesssDepartment();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    客户端代码:

    public static void main(String[] args) {
            User user = new User();
            Department department = new Department();
    
            //IFactory factory=new SqlServerFactory();
            IFactory factory=new AccessFactory();
    
            IUser iu=factory.CreateUser();
            iu.Insert(user);
            iu.GetUser(1);
    
            IDepartment id=factory.CreateDepartment();
            id.GetUser(1);
            id.Insert(department);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出代码:

    Access中给user表增加一条记录
    在Access中根据ID得到user表一条记录
    在Access中根据ID得到Department表一条记录
    在Access中给Department表增加一条记录
    
    • 1
    • 2
    • 3
    • 4

    总结:
    看完代码,我们可以看出抽象工厂模式是对于工厂方法的迭代升级,抽象工厂模式是针对于多对多的关系。可以增加新的产品线(方法)。

    缺点:抽象工厂模式在于难以应付“新对象”的需求变动,比如我在加一个数据库。难以支持新种类的产品。

    优点:分离具体的类,客户端通过抽象接口操纵实例,产品的类名也在具体工厂实现中被分离,不会出现在客户端代码中。

  • 相关阅读:
    Python 数独求解器
    拼团小程序制作技巧大揭秘:零基础也能轻松掌握
    QQ轰炸代码
    程序后台运行
    懒羊羊闲话1
    HTML超链接标签
    Windows搭建MQTT服务器
    Idea创建JavaEE项目
    【无标题】
    Go Web---Web服务器
  • 原文地址:https://blog.csdn.net/zhaoyangyj/article/details/127910437