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

概念

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;
    }
}

其他具体逻辑类

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;
    }
}

简单运算工厂类

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;
    }
}

客户端代码

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);
    }
}

实现

3.0

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

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

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

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

2.工厂方法案例及解析

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

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

代码:

雷锋类:

public class LeiFeng {
    public void Sweep(){
        System.out.println("扫地");
    }

    public void Wash(){
        System.out.println("洗衣");
    }

    public void BuyRice(){
        System.out.println("买米");
    }
}

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

public class Undergraduate extends LeiFeng{

}

public class Volunteer extends LeiFeng {
}

雷锋工厂

public interface IFactory {
    LeiFeng CreateLeiFeng();
}

继承雷锋精神的人

学生工厂:

public class UndergraduateFactory implements IFactory {
    @Override
    public LeiFeng CreateLeiFeng() {
        return new Undergraduate();
    }
}

社区志愿者工厂:

public class VolunteerFactory implements IFactory {
    @Override
    public LeiFeng CreateLeiFeng() {
            return new Volunteer();
    }
}

客户端代码:

public class Test {
    public static void main(String[] args) {
        IFactory factory=new UndergraduateFactory();
        LeiFeng student=factory.CreateLeiFeng();

        student.Sweep();
        student.BuyRice();
        student.Wash();
    }
}

实现:

扫地
买米
洗衣

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

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

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

3.抽象工厂案例及解析

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

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

IUser接口

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

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;
    }
}
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;
    }
}
public class SqlServerFactory implements IFactory {
    @Override
    public IUser CreateUser() {
        return new SqlserverUser();
    }

    @Override
    public IDepartment CreateDepartment() {
        return new SqlserverDepartment();
    }
}

从这里开始就是 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;
    }
}

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;
    }
}

public class AccessFactory implements IFactory {
    @Override
    public IUser CreateUser() {
        return new AccessUser();
    }

    @Override
    public IDepartment CreateDepartment() {
        return new AccesssDepartment();
    }
}

客户端代码:

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);

    }

输出代码:

Access中给user表增加一条记录
在Access中根据ID得到user表一条记录
在Access中根据ID得到Department表一条记录
在Access中给Department表增加一条记录

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值