工厂模式

工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、工厂方法模式以及抽象工厂模式。
类型:创建类模式。
它的主要优点有:
- 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
- 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
- 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。

1:简单工厂模式
代码:

//创建共同的接口
public interface IProduct{
    public void Method();
}
//创建实现类
public class A implements IProduct {
    @Override
    public void Method() {
        System.out.println("this is A Product!");
    }
}
public class B implements IProduct {
    @Override
    public void Method() {
        System.out.println("this is B Product!");
    }
}
//创建工厂类
public class Factory {
    public static IProduct produceA(){
        return new A();
    }
    public static IProduct produceB(){
        return new B();
    }
}
//测试
public class FactoryTest {
    public static void main(String[] args) {    
        IProduct product = Factory.produceA();
        product.Method();
    }
}

2:工厂方法模式
定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

类图:
这里写图片描述

代码:

interface IProduct {
    public void productMethod();
}
class Product implements IProduct {
    public void productMethod() {
        System.out.println("产品");
    }
}
interface IFactory {
    public IProduct createProduct();
}
class Factory implements IFactory {
    public IProduct createProduct() {
        return new Product();
    }
}
public class Client {
    public static void main(String[] args) {
        IFactory factory = new Factory();
        IProduct prodect = factory.createProduct();
        prodect.productMethod();
    }
}

通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:
1. 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
2. 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
3. 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
4. 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。

前文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱。

适用场景:
- 首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
- 其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。

典型应用:
要说明工厂模式的优点,可能没有比组装汽车更合适的例子了。场景是这样的:汽车由发动机、轮、底盘组成,现在需要组装一辆车交给调用者。假如不使用工厂模式,代码如下:

class Engine {
    public void getStyle(){
        System.out.println("这是汽车的发动机");
    }
}
class Underpan {
    public void getStyle(){
        System.out.println("这是汽车的底盘");
    }
}
class Wheel {
    public void getStyle(){
        System.out.println("这是汽车的轮胎");
    }
}
public class Client {
    public static void main(String[] args) {
        Engine engine = new Engine();
        Underpan underpan = new Underpan();
        Wheel wheel = new Wheel();
        ICar car = new Car(underpan, wheel, engine);
        car.show();
    }
}

可以看到,调用者为了组装汽车还需要另外实例化发动机、底盘和轮胎,而这些汽车的组件是与调用者无关的,严重违反了迪米特法则,耦合度太高。并且非常不利于扩展。另外,本例中发动机、底盘和轮胎还是比较具体的,在实际应用中,可能这些产品的组件也都是抽象的,调用者根本不知道怎样组装产品。假如使用工厂方法的话,整个架构就显得清晰了许多。

interface IFactory {
    public ICar createCar();
}
class Factory implements IFactory {
    public ICar createCar() {
        Engine engine = new Engine();
        Underpan underpan = new Underpan();
        Wheel wheel = new Wheel();
        ICar car = new Car(underpan, wheel, engine);
        return car;
    }
}
public class Client {
    public static void main(String[] args) {
        IFactory factory = new Factory();
        ICar car = factory.createCar();
        car.show();
    }
}

使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的,以后如果想组装其他的汽车,只需要再增加一个工厂类的实现就可以。无论是灵活性还是稳定性都得到了极大的提高。

3:抽象工厂模式
定义:
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

类图:
这里写图片描述

抽象工厂模式与工厂方法模式的区别:
工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品等级结构表现为一个接口或者抽象类。也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
如果工厂的产品全部属于同一个产品等级结构,则属于工厂方法模式;如果工厂的产品来自多个产品等级结构,则属于抽象工厂模式。

代码:

//产品等级结构A
interface IProductA {
    public void show();
}
//产品等级结构B
interface IProductB {
    public void show();
}
//实现产品等级结构A的两类产品1和2
class ProductA1 implements IProductA {
    public void show() {
        System.out.println("这是A型产品1号");
    }
}
class ProductA2 implements IProductA {
    public void show() {
        System.out.println("这是A型产品2号");
    }
}
//实现产品等级结构B的两类产品1和2
class ProductB1 implements IProductB {
    public void show() {
        System.out.println("这是B型产品1号");
    }
}
class ProductB2 implements IProductB {
    public void show() {
        System.out.println("这是B型产品2号");
    }
}
//工厂接口
interface IFactory {
    public IProductA createProductA();
    public IProductB createProductB();
}
//生产1号产品的工厂
class Factory1 implements IFactory{
    public IProductA createProductA() {
        return new ProductA1();
    }
    public IProductB createProductB() {
        return new ProductB1();
    }
}
//生产2号产品的工厂
class Factory2 implements IFactory{
    public IProductA createProductA() {
        return new ProductA2();
    }
    public IProductB createProductB() {
        return new ProductB2();
    }
}
public class Client {
    public static void main(String[] args){
        //生产1号产品
        IFactory factory = new Factory1();
        factory.createProductA().show();
        factory.createProductB().show();
    }
}

抽象工厂模式的优点:
由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得十分容易,它只需要改变具体工厂就可以在相同的产品等级结构配置下(如上述例子中的A和B)使用不同的产品(如上述例子中的1或2)。让具体的创建实例过程与客户端分离,客户端通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂类的实现隔离,不会出现在客户端代码中。

抽象工厂模式的缺点:
产品等级结构中需要增加一类新的产品时,需添加、修改多个类。所以使用抽象工厂模式时,对产品等级结构的划分非常重要。

适用场景:
一个继承体系中,如果存在着多个产品等级结构(即存在着多个抽象类),并且分属各个产品等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个产品等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

4:总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底是工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使得提供的产品不再构成不同等级结构的产品后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值