二、工厂模式

一、简单工厂模式

        简单工厂模式又 叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

public abstract class Operation {
    public abstract float getResult(float firstNumber, float secondNumber);
}


//把符号都当做对象处理,实现此接口
public class AddOperation extends Operation {
    @Override
    public float getResult(float firstNumber, float secondNumber) {
        return firstNumber+secondNumber;
    }
}



public class SubOperation extends Operation {
    @Override
    public float getResult(float firstNumber, float secondNumber) {
        return firstNumber-secondNumber;
    }
}


public class MulOperation extends Operation {
    @Override
    public float getResult(float firstNumber, float secondNumber) {
        return firstNumber*secondNumber;
    }
}


public class DivOperation extends Operation {
    @Override
    public float getResult(float firstNumber, float secondNumber) {
        return firstNumber/secondNumber;
    }
}


//接下来需要解决的就是对象的创建问题了,既如何根据不同的情况创建不同的对象:我们正好可以通过简单工厂模式实现
public class OperationFactory {

    public static Operation getOperation(String quotaFlag){
        Operation o = null;
        switch (quotaFlag){
            case "+" :  o = new AddOperation();
            case "-" :  o = new SubOperation();
            case "*" :  o = new MulOperation();
            case "/" :  o = new DivOperation();
            default:break;
        }
        return o;
    }
}


//调用:
public class Computer {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入第一个数字:");
        float firstNum  = in.nextFloat();
        System.out.println("请输入第二个数字:");
        float secondNum  = in.nextFloat();
        System.out.println("请输入运算符号:");
        String countQuato = in.next();
        System.out.println(count(firstNum,secondNum,countQuato));
    }
    private static float count(float firstNum,float secondNum , String countQuota){
    //通过工厂类获取对象
        Operation operation = OperationFactory.getOperation(countQuota);
        return operation.getResult(firstNum,secondNum);
    }
}

        简单工厂将对象的创建过程进行了封装,用户不需要知道具体的创建过程,只需要调用工厂类获取对象即可。

        这种简单工厂的写法是通过switch-case来判断对象创建过程的。在实际使用过程中,违背了 开放-关闭原则,当然有些情况下可以通过反射调用来弥补这种不足。

二、工厂方法模式

        工厂方法 定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使得一个类的实例化延迟到了子类 

        工厂方法在简单工厂的基础上再包了一层工厂,所有的工厂都是此工厂的子类。而产生对象的类型由子类工厂决定。使用工厂方法来实现上面的加减乘除对象的创建

//定义上级工厂的接口
public interface IFractory {
    public Operation generateOper();
}


//为每一个类创建工厂
/**
 * 工厂方法  为每个对象生成一个工厂类
 */
public class AddOperationFactory implements IFractory{

    @Override
    public Operation generateOper() {
        return new AddOperation();
    }
}


public class SubOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new SubOperation();
    }
}


public class MulOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new MulOperation();
    }
}


public class DivOperationFactory implements IFractory {
    @Override
    public Operation generateOper() {
        return new DivOperation();
    }
}




//客户端代码

IFractory fractory = new AddOperationFactory();

Operation operation = fractory.generateOper();

operation.getResult(firstNum,secondNum);

        工厂方法将类的实例化推迟到了其子类。所以使用工厂方法模式时,需要客户端决定实例化哪一个工厂类。选择判断问题还是存在的。也就是说,工厂方法把简单的工厂内部逻辑判断转移到了客户端来运行。你想要加的功能,本来是要改工厂类的,而现在是修改客户端。不过,我们在某些情况下通过工厂方法,只需要修改一行实例化的代码就可以实现系统元素的切换(比如切换数据源)。这也是很方便的。

三、抽象工厂模式

        提供一个创建一系列相关相互依赖对象的接口,而无需指定他们具体的类。抽象工厂为不同产品族的对象创建提供接口。 

使用场景:系统需要在不同产品族进行切换 

代码实现:

public interface IFacfory {
    public IUser createUser();
    public IDepartment createDepartment();
}


public interface IUser {
    public void insert();
    public void getById();
}


public interface IDepartment {
    public void insert();
    public void getDepartmentById();
}



public class SqlServerUser implements IUser {
    @Override
    public void insert() {
        System.out.println("insert into sqlserver.");
    }

    @Override
    public void getById() {
        System.out.println("get user by id from sqlserver.");
    }
}


public class SqlServerDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("insert department into sqlserver.");
    }

    @Override
    public void getDepartmentById() {
        System.out.println("get department in sqlserver by id.");
    }
}



public class AccessUser implements IUser {
    @Override
    public void insert() {
        System.out.println("insert into access");
    }

    @Override
    public void getById() {
        System.out.println("get by id from access");
    }
}


public class AccessDepartment implements IDepartment {
    @Override
    public void insert() {
        System.out.println("insert department into sqlserver.");
    }

    @Override
    public void getDepartmentById() {
        System.out.println("get department in sqlserver by id.");
    }
}


//不同产品组使用一个工厂
public class SqlServerFactory implements IFacfory {
    @Override
    public IUser createUser() {
        return new SqlServerUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new SqlServerDepartment();
    }
}



public class AccessFactory implements IFacfory {
    @Override
    public IUser createUser() {
        return new AccessUser();
    }

    @Override
    public IDepartment createDepartment() {
        return new AccessDepartment();
    }
}

客户端:

IFacfory facfory = new AccessFactory();

IUser user = facfory.createUser();

IDepartment department = facfory.createDepartment();

user.insert();

user.getById();

department.insert();

department.getDepartmentById();

        抽象工厂最大的好处就是便于交换产品系列,具体工厂在代码中一般只出现一次。这就使得改变应用的具体工厂很容易。

        第二个好处是他能让具体的创建对象实例和客户端分离,客户端是通过他们的抽象接口操作实例

        抽象工厂不太易于拓展,如果需要自增功能,或者自增产品,则需要至少修改三个类,而且实例化的代码是写死在程序中的 , 这样无法避免违背开放-关闭原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的IT蜗牛

更美口味,打赏人生

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值