工厂模式和策略模式

一、工厂模式

1.1简单工厂模式实现计算器

一般实现的计算器需要在客户端进行逻辑判断,在添加新的功能的时候需要修改很多的代码,而用简单工厂模式可以将逻辑判断的代码放在后台,而且在添加新的功能的时候也很容易。在不用的应用中也能复用。

首先创建Operation抽象类,将公有的方法getResult()设置为抽象函数

 public abstract class Operation {
    private double numberA;
    private double numberB;

    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 abstract double getResult();
}

 

对于不同的操作,创建不同的操作类,继承抽象操作类,然后各自实现抽象方法。

class OperationAdd extends Operation {
    @Override
    public double getResult() {
        return getNumberA() + getNumberB();

    }
}

class OperationSub extends Operation {
    @Override
    public double getResult() {
        return getNumberA() - getNumberB();

    }
}
class OperationMul extends Operation {
    @Override
    public double getResult() {
        return getNumberA() * getNumberB();

    }
}
class OperationDiv extends Operation {
    @Override
    public double getResult() {
        if(getNumberB()==0){
            System.out.println("除数不能为0");
            return 0;
        }else{
            return getNumberA() * getNumberB();
        }

    }
}

然后,创建工厂类,根据字符串参数,实例化不同的操作类

public class OperationFactory {
    public static Operation createOperation(String oper){
        Operation operation=null;
        switch (oper){
            case "+":
                operation=new OperationAdd();
                break;
            case "-":
                operation=new OperationSub();
                break;
            case "*":
                operation=new OperationMul();
                break;
            case "/":
                operation=new OperationDiv();
                break;
            }

        return operation;
    }

}

最后进行测试

 工厂模式和策略模式

在简单工厂模式中,添加新的操作

首先,创建新的操作类,

class OperationPower extends Operation{
    @Override
    public double getResult() {
        return Math.pow(getNumberA(),getNumberB());
    }
}

其次,在工厂类中添加switch条件

        case "pow":
                operation=new OperationPower();

这样就添加了新的功能,测试如下:

 工厂模式和策略模式

 

1.2工厂方法模式

虽然简单工厂模式已经很好的实现了抽象和封装,但是它违反了开闭原则,开闭原则要求面向拓展开放而面向修改封闭,而且对于简单工厂模式,客户端只能通过传参数的方式控制类型,这样对于拥有用户界面的程序很有用,但是对于没有用户界面的程序,其他程序本身无法直接生成不同的操作符,这样就需要工厂方法模式。

 

Operation类保持不变

创建IFactory接口,然后对每个类型的操作符创建不同的接口,实现IFactory接口

public interface IFactory {
    Operation createOperation();
}
class AddFactory implements IFactory{
    @Override
    public Operation createOperation() {
        return new OperationAdd();
    }
}
class SubFactory implements IFactory{
    @Override
    public Operation createOperation() {
        return new OperationSub();
    }
}
class MulFactory implements IFactory{
    @Override
    public Operation createOperation() {
        return new OperationMul();
    }
}
class DivFactory implements IFactory{
    @Override
    public Operation createOperation() {
        return new OperationDiv();
    }
}

 

这样在添加新的功能的时候,在后台只需要添加一个operation类和一个factory类,不需要进行修改,只需要修改前端调用的代码,符合开闭原则。

1.3抽象工厂模式

抽象工厂模式是用于创建一系列相关的对象的抽象接口,当工厂方法模式的对象为多个的时候,就要使用抽象工厂模式

用抽象工厂模式实现可移植的数据库访问。假设一个程序可能链接access数据库和sql server数据库,利用抽象工厂模式可以使数据库在改变是代码的修改最少。

假设数据库里面有一个用户User和产品Product表,首先创建者两个类

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 Product {
    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 interface IUser {
    void insert(User user);
    User getUser(int id);
}

  

public interface IProduct {
    void insert(Product product);
    Product getProduct(int id);
} 

根据不同的数据库实现接口

对于User

public class SqlserverUser implements IUser{
    @Override
    public void insert(User user) {
        System.out.println("Sqlserver 插入User表");
    }

    @Override
    public User getUser(int id) {
        System.out.println("Sqlserver 查找User表");
        return null;
    }
}

 

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 查找User表");
        return null;
    }
}

对于product

public class SqlserverProduct implements IProduct {
    @Override
    public void insert(Product product) {
        System.out.println("Sqlserver 插入Product表");
    }

    @Override
    public Product getProduct(int id) {
        System.out.println("Sqlserver 查找Product表");
        return null;
    }
}

public class AccessProduct implements IProduct {
    @Override
    public void insert(Product product) {
        System.out.println("Access 插入Product表");
    }

    @Override
    public Product getProduct(int id) {
        System.out.println("Access 查找Product表");
        return null;
    }
}

创建抽象工厂接口

public interface IFactory {
    IUser CreateUser();
    IProduct CreateProduct();
}

创建sqlserverFactory

public class SqlaerverFactory implements IFactory {
    @Override
    public IUser CreateUser() {
        return new SqlserverUser();
    }

    @Override
    public IProduct CreateProduct() {
        return new SqlserverProduct();
    }
}

 

创建AccessFactory

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

    @Override
    public IProduct CreateProduct() {
        return new AccessProduct();
    }
}

 

然后进行测试

public class AbstractFacTest {
    public static void main(String[] args) {
        User user=new User();
        Product product=new Product();
        //对于sql server数据库
        IFactory database=new SqlaerverFactory();
        //对于Access数据库
        //IFactory database=new AccessFactory();
        IUser iUser=database.CreateUser();
        iUser.insert(user);
        iUser.getUser(1);
        IProduct iProduct=database.CreateProduct();
        iProduct.insert(product);
        iProduct.getProduct(1);
    }
}

只需更改一句就能移植到其他数据库。

运行结果为:

 工厂模式和策略模式

当修改后

 工厂模式和策略模式

二、策略模式

商场经常会有不同的活动,加钱也会发生变化,如打八折和满30080现在为商城设计一个软件,输入商品价格,根据不同的优惠返回最后要付的值,这种使用一系列不同算法的软件可以用策略模式进行设计。

先定义所有算法的公告接口CashSuper

public interface CashSuper {
    double acceptCashh(double money);
} 

然后创建封装的具体的算法类

class CashNormal implements CashSuper{
    @Override
    public double acceptCashh(double money) {
        return money;
    }
}
class CashRebate implements CashSuper{
    private double moneyRebate=1.0;

    public CashRebate(double moneyRebate){
        this.moneyRebate=moneyRebate;
    }

    @Override
    public double acceptCashh(double money) {
        return money*moneyRebate;
    }
}
class CashReturn implements CashSuper{
    private double moneyCondition=1.0;
    private double moneyReturn=1.0;

    public  CashReturn(double moneyCondition,double moneyReturn){
        this.moneyCondition=moneyCondition;
        this.moneyReturn=moneyReturn;
    }

    @Override
    public double acceptCashh(double money) {
        double result=money;
        if(money>=moneyCondition){
            result= money-Math.floor(money/moneyCondition)*moneyReturn;
        }
        return result;
    }
} 

创建一个Context完成对strategy的引用

public class CashContext {
    private CashSuper cs;
    public CashContext(String choose){
        switch (choose){
            case "无优惠":
                cs=new CashNormal();
                break;
            case "打八折":
                cs=new CashRebate(0.8);
                break;
            case "满300减80":
                cs=new CashReturn(300,80);
        }
    }
    public double getResult(double money){
        return cs.acceptCashh(money);
    }
}

在创建CashContext的时候使用了简单工厂模式,这样在test程序使用的时候,Test程序只用知道Context而不需要知道strategy类,降低了耦合

public class StrategyTest {
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        System.out.println("计算类别");
        System.out.println("无优惠");
        System.out.println("打八折");
        System.out.println("满300减80");
        System.out.println("请输入金额");
        double money=Double.parseDouble(in.nextLine());
        System.out.println("请输入选择计算类别:");
        String choose=in.nextLine();
        CashContext cashContext=new CashContext(choose);
        System.out.printf("结果为%f",cashContext.getResult(money));
    }
}

运算结果为:

 工厂模式和策略模式