zoukankan      html  css  js  c++  java
  • 设计模式(一)——工厂方法模式

    设计模式(一)——工厂方法模式

    概念

    工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。

    定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。

    适用性

    在下列情况下可以使用工厂方法模式:

    • 当一个类不知道它所创建的对象的类的时候
    • 当一个类希望由它的子类来指定它所创建的对象的时候
    • 当类创建对象的职责委托给多个帮助子类的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候

    类图

    Alt 工厂方法模式类图

    代码实现

    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();
    	}
    }
    
    

    四个要素

    从类图中,我们可以发现,工厂方法模式由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();
    	}
    }
    

    优缺点

    优点

    • 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
    • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
    • 主要目的是为了解耦。在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

    缺点

    • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
    • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。

    参考资料

    http://www.hollischuang.com/archives/1401

    http://blog.csdn.net/zhengzhb/article/details/7348707

  • 相关阅读:
    Win8系统 Python安装
    一些安卓开源框架整理
    Android 媒体键监听以及模拟媒体键盘的实现 demo
    android View 自动 GONE 问题
    Android 定时器TimerTask 简单使用
    关于Android studio 相对 eclipse 优点
    Java序列化与反序列化
    android shape的使用 边框
    Android Studio 修改 包名 package name
    Android WebView Long Press长按保存图片到手机
  • 原文地址:https://www.cnblogs.com/yy1024/p/5704590.html
Copyright © 2011-2022 走看看