设计模式篇---工厂方法(可通过lambda实现)

文章目录

    • 概念
    • 结构
    • 实例
    • 通过lambda实现
    • 总结

概念

工厂方法模式:定义一个用于创建对象的接口,但是让子类决定将哪个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
这个模式还是比较好理解,且使用场景比较频繁。简单工厂是只有一个工厂类,通过if else 根据不同的参数返回对应的对象;而工厂方法去除了if else 的判断,更加的灵活,它把返回对象的功能交给了子类(而简单工厂是将返回对象的功能交给了一个固定的工厂类),通过扩展子类来实现不同的功能。

结构

工厂方法的类图如下:
设计模式篇---工厂方法(可通过lambda实现)_第1张图片
Product(抽象产品):定义产品的接口,具体产品对象的父类。
ConcreateProduct(具体产品):实现了抽象产品类的方法,它与具体的工厂一一对应。
Factory(抽象工厂):它声明了抽象的方法,用来返回一个产品,所有具体的工厂都要实现该接口。
ConcreateFactory(具体工厂):它是抽象工厂的子类,返回具体的产品,与具体产品类一一对应。

实例

我们可以实现一个简单的计算器,拥有加减乘除四个算法,每个算法对应一个工厂类。

产品的抽象类,即抽象的操作类

public abstract class Operation {

    private Integer a;

    private Integer b;

    abstract Integer operation(Integer a, Integer b);

}

具体的加减乘除类四个类,继承父类Operation。

public class AddOperation extends Operation {

    @Override
    Integer operation(Integer a, Integer b) {
        return a + b;
    }
}
public class SubOperation extends Operation {

    @Override
    Integer operation(Integer a, Integer b) {
        return a - b;
    }
}
public class MultiOperation extends Operation {

    @Override
    Integer operation(Integer a, Integer b) {
        return a * b;
    }
}

public class DivOperation extends Operation {

    @Override
    Integer operation(Integer a, Integer b) {
        return a / b;
    }
}

抽象的工厂,四个工厂的接口,定义了抽象的计算方法。

public interface OperationFactory {

    //返回抽象的产品,子类返回具体的产品---里氏替换
    Operation createOperation();
}

四个具体的工厂类

public class AddFactory implements OperationFactory {

    @Override
    public Operation createOperation() {
        return new AddOperation();
    }
}
public class SubFactory implements OperationFactory {
    @Override
    public Operation createOperation() {
        return new SubOperation();
    }
}
public class MultiFactory implements OperationFactory {
    @Override
    public Operation createOperation() {
        return new MultiOperation();
    }
}
public class DivFactory implements OperationFactory {

    @Override
    public Operation createOperation() {
        return new DivOperation();
    }
}

客户端

public class Client {

    public static void main(String[] args) {

        //处理加法
        OperationFactory addFactory= new AddFactory();
        Operation operation = addFactory.createOperation();
        System.out.println(operation.operation(1, 2));


        //处理减法
        OperationFactory subFactory= new SubFactory();
        Operation operation1 = subFactory.createOperation();
        System.out.println(operation1.operation(1, 2));

        // 乘法、除法同上
    }
}

通过lambda实现

如果继续扩展的话,我们不用改动原来的代码,只需要再增加一个产品对象和对应的产品工厂就好了,非常符合开闭原则。但是如果有100个算法,我们就要创建100个具体产品类和100个具体产品工厂,维护起来太难了。如果我们用jdk8或者以上版本的话,可以通过lamda进行简化,不需要创建具体的类了,直接通过参数行为化来搞。

思路是这样:因为加减乘除这四个算法的入参和返回值的类型都是一样的(入参都是两个数,返回值都是一个数),这样就可以搞一个函数式接口,里面的抽象方法入参是两个数,返回值是一个数。然后将加减乘除四个算法的具体实现写在外面进行参数行为化。实现如下:

计算的函数式接口,入参数是T类型,返回值是V类型,如果只用来进行数的计算,可以直接写成Integer类型。

public interface Operate<T, V> {
    V operation(T a, T b);
}

客户端直接搞。

public class Client {

    static Map<String, Operate<Integer, Integer>> map = new HashMap<>();

    static {
        map.put("add", (a, b) -> {
            return (a + b);
        });

        map.put("sub", (a, b) -> {
            return (a - b);
        });
    }
    public static void main(String[] args) {

        //执行加法
        Integer add = map.get("add").operation(1, 2);
        System.out.println(add);


        //执行减法
        Integer sub = map.get("sub").operation(1, 2);
        System.out.println(sub);

    }
}

通过lambda,可以将计算的实现写在map的value里面。可以将map单独放在一个类里进行维护,当有新的计算操作时,就只维护这一个map的类就可以了(只需要执行put方法,但从一定程度上不符合开闭原则)。

总结

先说两个特别重要的概念:
里氏替换:子类型必须能够替换掉他们的基类型。
依赖倒置:高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象

工厂方法比简单工厂更符合开闭原则,当有新的需求时,不用修改之前代码。
客户端关注的是抽象的产品,具体工厂里返回的是具体的产品,这就必须让子产品永远可以替代父产品,我们维护每一个工厂类都是在管理具体的子产品。具体工厂对应抽象工厂也是同理。这就是里氏替换的应用。

客户端没有直接面向具体产品和具体工厂,而是依赖抽象产品和抽象工厂,这是高层依赖了抽象,具体产品和具体工厂实现了各自的抽象类,这是低层依赖了抽象。这是依赖倒置的应用。

最后肯定是符合开闭原则的。

你可能感兴趣的:(设计模式,设计模式,java,开发语言)