设计模式之工厂模式

工厂模式可以细分为:简单工厂、工厂方法和抽象工厂三种模式。

使用场景

总体而言工厂模式的使用场景分为两种:

  1. 单个对象的创建过程比较复杂,如需要做复杂初始化操作的对象

  2. 需要根据不同的类型创建不同的对象

针对细分的三种模式,使用场景又可以区分:

  1. 当**「对象的创建逻辑简单」,通常只需要new一下就可以,此时可以考虑「简单工厂模式」**

  2. 当**「对象的创建逻辑很复杂」,需要做各种初始化操作,此时可以考虑使用「工厂方法模式」**,将对象创建的复杂逻辑拆分到各个工厂类中,让每个工厂类都不至于过于复杂

  3. 当**「系统中有多于一个产品族」,而每次只使用其中某一产品族,此时使用「抽象工厂模式」**

简单工厂模式

类图

图片

ProcuctA和ProductB继承Product抽象类,ProductFactory根据传入的type来返回不同的Product实例

代码实现

Product
public abstract class Product {
    public abstract void use();
}

ProductA
public class ProductA extends Product {
    @Override
    public void use() {
        System.out.println("You are using ProductA...");
    }
}

ProductB
public class ProductB extends Product {
    @Override
    public void use() {
        System.out.println("You are using ProductB...");
    }
}

ProductFactory
public class ProductFactory {
    public Product createProduct(String type) {
        Product product = null;
        if ("A".equals(type)) {
            product = new ProductA();
        } else if ("B".equals(type)) {
            product = new ProductB();
        }
        return product;
    }
}

Main
public class Main {
    public static void main(String[] args) {
        ProductFactory factory = new ProductFactory();
        Product product;

        product = factory.createProduct("A");
        product.use();

        product = factory.createProduct("B");
        product.use();
    }
}

点评

当频繁的新增不同产品时,需要频繁地修改ProductFactory中的if/else逻辑

应用

JDK

java.text.DateFormat#getDateInstance()
java.text.DateFormat#getDateInstance(int)
java.text.DateFormat#getDateInstance(int, java.util.Locale)

加密类,获取不同加密算法的密钥生成器:

KeyGenerator keyGen=KeyGenerator.getInstance("DESede");

工厂方法模式

类图

图片

相比简单工厂,这种方式将ProductFactory定义为抽象类,然后创建不同的具体的ProductAFactoryProductBFactory,在使用时决定创建哪种工厂和对象,避免了if/else判断

代码实现

Product
public abstract class Product {
    public abstract void use();
}

ProductA
public class ProductA extends Product {
    @Override
    public void use() {
        System.out.println("You are using ProductA...");
    }
}

ProductB
public class ProductB extends Product {
    @Override
    public void use() {
        System.out.println("You are using ProductB...");
    }
}

ProductFactory
public abstract class ProductFactory {
    public abstract Product createProduct();
}

ProductAFactory
public class ProductAFactory extends ProductFactory {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

ProductBFactory
public class ProductBFactory extends ProductFactory {
    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

Main
public class Main {

    public static void main(String[] args) {
        ProductFactory factory;
        Product product;

        factory = new ProductAFactory();
        product = factory.createProduct();
        product.use();

        factory = new ProductBFactory();
        product = factory.createProduct();
        product.use();
    }

}

点评

这种模式更加符合开闭原则,但是与最原始的new ProductA()new ProductA()相比非常相似,引入工厂模式,反倒让设计变得更加复杂了。

应用

JDBC

Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db1","db_user","123456");
Statement statement=conn.createStatement();
ResultSet rs=statement.executeQuery("select * from user");

抽象工厂模式

为了理解抽象工厂模式,我们要先了解两个概念:

  • 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

  • 产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品。一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

类图

图片

Factory1负责创建ProductA1ProductB1``Factory2负责创建ProductA2ProductB2客户端不需要知道具体的产品,只需要知道创建的工厂即可使用该产品

代码实现

AbstractProductA
public abstract class AbstractProductA {

    public abstract void use();

}

ProductA1
public class ProductA1 extends AbstractProductA {

    @Override
    public void use() {
        System.out.println("You are using ProductA1...");
    }

}

ProductA2
public class ProductA2 extends AbstractProductA {

    @Override
    public void use() {
        System.out.println("You are using ProductA2...");
    }

}

AbstractProductB
public abstract class AbstractProductB {

    public abstract void eat();

}

ProductB1
public class ProductB1 extends AbstractProductB {

    @Override
    public void eat() {
        System.out.println("You are eating ProductB1...");
    }

}

ProductB2
public class ProductB2 extends AbstractProductB {

    @Override
    public void eat() {
        System.out.println("You are eating ProductB2...");
    }

}

AbstractFactory
public abstract class AbstractFactory {

    public abstract AbstractProductA createProductA();

    public abstract AbstractProductB createProductB();

}

Factory1
public class Factory1 extends AbstractFactory {

    @Override
    public AbstractProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB1();
    }

}

Factory2
public class Factory2 extends AbstractFactory {

    @Override
    public AbstractProductA createProductA() {
        return new ProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB2();
    }

}

Main
public class Main {

    public static void main(String[] args) {
        AbstractFactory factory;
        
        factory = new Factory1();
        use(factory);

        factory = new Factory2();
        use(factory);
    }

    public static void use(AbstractFactory factory) {
        AbstractProductA productA = factory.createProductA();
        productA.use();
        AbstractProductB productB = factory.createProductB();
        productB.eat();
    }

}

点评

抽象工厂模式带来了众多类,结构相对复杂,且创建新的产品等级结构麻烦。抽象工厂模式实际工作中应用场景很少,简单关注了解下即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值