工厂模式
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(接口)
不要覆盖基类中已经实现的方法。
使用场景:
当只有一个工厂,且整个业务逻辑是两层树结构,工厂——>实例,这种适合简单工厂。这时只是对创造类的实例进行统一管理。
当不只有一个工厂,且整个业务逻辑是三层树结构,类型->某类型工厂->实例,这种适合工厂方法模式。
当不只有一个工厂,且整个业务逻辑是三层树结构,且需要多个工厂,这时候需要每个工厂不止生产一个类型的实例,这种场景适合抽象工厂模式