Design Pattern

工厂模式

2020-10-14  本文已影响0人  乙腾

case

产品订单,有两类产品,每类有两个品牌
冰箱:格力冰箱,海尔冰箱
电视:海尔电视,格力电视

传统code

ProductOrder

package com.pl.designMode.factory.simple;

import com.pl.designMode.factory.simple.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName SimpleDemo
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class ProductOrder {

    Product product;

    public ProductOrder(String instanceName){
        if ("geliRefrigerator".equals(instanceName)){
            this.product= new GeLiRefrigerator();
        }else if ("HaiErRefrigerator".equals(instanceName)){
            this.product=new HaiErRefrigerator();
        }else if ("gelitv".equals(instanceName)){
            this.product=new GeLiTv();
        }else if ("hairetv".equals(instanceName)){
            this.product = new HaiErTv();
        }
        System.out.println(product.toString());
    }
}

优缺点

优点:

线性思维,通过ifelse进行业务逻辑判断,好想好写

缺点:

违反ocp原则,即对扩展开放,对修改关闭。当需要添加一类品牌或者种类时,就需要改动ProductOrder的ifelse代码块。

简单工厂模式

code

SimpleFactory

package com.pl.designMode.factory.simpleFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName SimpleFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class SimpleFactory {

    private Product product;

    public Product createProduct(String instanceName){
        if (instanceName.equalsIgnoreCase("GeLiRefrigerator")){
            product = new GeLiRefrigerator();
        }else if (instanceName.equalsIgnoreCase("GeLiTv")){
            product = new GeLiTv();
        }else if (instanceName.equalsIgnoreCase("HaiErRefrigerator")){
            product = new HaiErRefrigerator();
        }else if (instanceName.equalsIgnoreCase("HaiErTv")){
            product = new HaiErTv();
        }
        return product;
    }
}

Product

package com.pl.designMode.factory.simpleFactory;

/**
 * @Auther: pl
 * @Date: 2020/10/14 20:57
 * @Description:
 */
public interface Product {
    void price();
}

HaiErTv

package com.pl.designMode.factory.simpleFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName HaiErTv
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiErTv implements Product {

    @Override
    public void price() {
        System.out.println("HaiErTv价格");
    }
}

Test

package com.pl.designMode.factory.simpleFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName Test
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class Test {
    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        Product geLiRefrigerator = simpleFactory.createProduct("GeLiRefrigerator");
        geLiRefrigerator.price();
    }
}

优缺点

优点:
和之前写的普通代码差不多,通过实例名字获取对应实例。
缺点:
依旧没有扩展性。如果客户端需要添加新产品,就必须在SimpleFactory加一个if判断。

工厂方法模式

code

ProductFactory

package com.pl.designMode.factory.factoryMethod;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName ProductFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public interface ProductFactory {
    Product create();
}

HaiErTvFactory

package com.pl.designMode.factory.factoryMethod;

import com.pl.designMode.factory.simpleFactory.GeLiRefrigerator;
import com.pl.designMode.factory.simpleFactory.GeLiTv;
import com.pl.designMode.factory.simpleFactory.HaiErTv;
import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName MethodFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiErTvFactory implements ProductFactory {

    @Override
    public Product create() {
        return new HaiErTv();
    }
}

HaiErRefrigeratorFactory

package com.pl.designMode.factory.factoryMethod;

import com.pl.designMode.factory.simpleFactory.GeLiRefrigerator;
import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName MethodFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiErRefrigeratorFactory implements ProductFactory {

    @Override
    public Product create() {
        return new HaiErGeLiRefrigerator();
    }
}

Test

package com.pl.designMode.factory.factoryMethod;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName Test
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class Test {
    public static void main(String[] args) {
       businessFun(new RefrigeratorFactory());
       businessFun(new TvFactory());
    }

    public static void businessFun(ProductFactory productFactory){
        Product product = productFactory.create();
        product.price();
    }
}

notice

n1:和简单工厂的区别

工厂方法:将工厂接口化,将创建实例方法抽象成抽象方法,将对象实例的过程推迟到子类工厂中创建。
简单工厂:工厂为普通类,在工厂类中创建实例。

n2:优缺点

优点:
可扩展,且不用改动业务代码。
如:新增一个洗衣机类型的产品,只需要在增加一个洗衣工厂即可,businessFun不需要任何改变,就可以调用小米的业务。符合ocp原则。
缺点:
当产品种类多的时候,则需要创建多个类别的工厂。这种工厂一类工厂只能生产一类产品。当在需要一个冰箱产品的时候,就得再创建一个冰箱工厂。
抽象工厂模式
code
AbstractFactory

package com.pl.designMode.factory.abstractFactory;

/**
 * @Auther: pl
 * @Date: 2020/10/14 22:41
 * @Description:
 */
public interface AbstractFactory {
    Refrigerator createRefrigerator();
    TV createTv();
}

GeliFactory

package com.pl.designMode.factory.abstractFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName GeliFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class GeliFactory implements AbstractFactory {

    @Override
    public Refrigerator createRefrigerator() {
        return new GeLiRefrigerator();
    }

    @Override
    public TV createTv() {
        return new GeLiTv();
    }
}

HaiReFactory

package com.pl.designMode.factory.abstractFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName HaiReFactory
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiReFactory implements AbstractFactory{
    @Override
    public Refrigerator createRefrigerator() {
        return new HaiErRefrigerator();
    }

    @Override
    public TV createTv() {
        return new HaiErTv();
    }
}

Refrigerator

package com.pl.designMode.factory.abstractFactory;

/**
 * @Auther: pl
 * @Date: 2020/10/14 22:51
 * @Description:
 */
public interface Refrigerator {
    void price();
}

GeLiRefrigerator

package com.pl.designMode.factory.abstractFactory;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName GeLiRefrigerator
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class GeLiRefrigerator implements Refrigerator {

    @Override
    public void price() {
        System.out.println("GeLiRefrigerator价格");
    }
}

HaiErRefrigerator

package com.pl.designMode.factory.abstractFactory;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName HarErRefrigerator
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiErRefrigerator implements Refrigerator {
    @Override
    public void price() {
        System.out.println("海尔冰箱价格");
    }
}

TV

package com.pl.designMode.factory.abstractFactory;

/**
 * @Auther: pl
 * @Date: 2020/10/14 22:51
 * @Description:
 */
public interface TV {
    void size();
}

GeLiTv

package com.pl.designMode.factory.abstractFactory;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName GeLiTv
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class GeLiTv implements TV {

    @Override
    public void size() {
        System.out.println("GeLiTv size");
    }
}

HaiErTv

package com.pl.designMode.factory.abstractFactory;

import com.pl.designMode.factory.simpleFactory.Product;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName HaiErTv
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class HaiErTv implements TV {

    @Override
    public void size() {
        System.out.println("HaiErTv size");
    }
}

Test

package com.pl.designMode.factory.abstractFactory;

/**
 * <p>
 *
 * @Description: TODO
 * </p>
 * @ClassName Test
 * @Author pl
 * @Date 2020/10/14
 * @Version V1.0.0
 */
public class Test {
    public static void main(String[] args) {
        businessFuc(new GeliFactory());
    }


    public static void businessFuc(AbstractFactory factory){
        Refrigerator refrigerator = factory.createRefrigerator();
        refrigerator.price();
        TV tv = factory.createTv();
        tv.size();
    }
}
image.png

notice
n1:和工厂方法的区别
区别:
工厂方法中的工厂只能生产一类产品。
抽象工厂模式中的工厂可以生产多类产品。
共同点:
都是将实例交给子工厂去实现。
n2:实现思路
1.将实例对象按照依赖关系分为不同的对象簇。
2.将工厂按照工厂抽象成两层,抽象工厂和具体实现工厂。每个工厂里面按照产品簇维护该类产品。
n3:产品簇,产品等级
按照产品簇定义工厂,按照产品等级定义实例对象接口。


image.png

n4:优缺点
优点:
可扩展,且不用维护过多的工厂。
缺点:
新增加产品簇确实不用修改代码,但是一旦新增对象簇(产品等级),就需要更改源码了,所有工厂都需要支持新的对象簇(产品等级)。

三种工厂的使用场景

简单工厂:

产品簇只有一个的时候,有多个产品。

工厂方法:

产品簇比较少的情况(无视产品等级的变化)。

抽象工厂:

产品簇多,且产品等级比较固定的情况。

工厂模式的总结

工厂模式的意义

将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

设计模式的依赖抽象原则

 创建对象实例时,不要直接 new 类, 而是把这个 new 类的动作放在一个工厂的方法中,并返回。有的书上说, 变量不要直接持有具体类的引用。
 不要让类继承具体类,而是继承抽象类或者是实现 interface(接口)
 不要覆盖基类中已经实现的方法。

使用场景:

当只有一个工厂,且整个业务逻辑是两层树结构,工厂——>实例,这种适合简单工厂。这时只是对创造类的实例进行统一管理。
当不只有一个工厂,且整个业务逻辑是三层树结构,类型->某类型工厂->实例,这种适合工厂方法模式。
当不只有一个工厂,且整个业务逻辑是三层树结构,且需要多个工厂,这时候需要每个工厂不止生产一个类型的实例,这种场景适合抽象工厂模式

上一篇下一篇

猜你喜欢

热点阅读