设计模式——工厂方法模式

所有的工厂模式都用来封装对象的创建。工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

设计原则

依赖倒置原则

要依赖抽象,不要依赖具体类

定义

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

如同定义中所说的,工厂方法让子类决定要实例化的类是哪一个。所谓的“决定”,并不是指模式允许子类本身再运行时做决定,而是指在编写创建者类时,不需要知道实际创建的产品是哪一个。选择了使用哪个子类,自然就决定了实际创建的产品是什么。

类图

设计模式——工厂方法模式_第1张图片

代码实现

我们还是以上面咖啡店为例。

一个大的咖啡店不可能只有一个,而是遍布在全国各地,上海、北京、深圳……都会有分店。而且如果经营的好,分店还会增加。

那么,每个地区的分店虽然都是售卖咖啡,但是为了满足各地区客户的需求偏好,也会根据当地特色有些许的不同。比如上海人喜欢吃甜的,那么上海分店可能生产出来的同样的咖啡味道为偏甜,北京人口味偏咸和鲜,讲究浓,那么同样的咖啡口味就会更浓,深圳属于南方,口味清淡,那可能就会是原味咖啡居多,不放牛奶也不放糖,浓淡适中……

对于咖啡厅,从制作好咖啡到送到客户手中还需要一系列步骤,比如打包……,而这个打包的过程程序就与咖啡的类别没有太大关系。

下面我们用代码来实现:

package com.study.design.Factory.factorymethod;

/**
 * 被生产对象的抽象父类
 */
public abstract class Coffe {

    protected String coffeName;

    public String getCoffeName() {
        return coffeName;
    }

}
package com.study.design.Factory.factorymethod;

public class SHLatteCoffe extends Coffe{

    public SHLatteCoffe(){
        coffeName = "shanghai latte";
    };
}
package com.study.design.Factory.factorymethod;

public class SHMochaCoffe extends Coffe{

    public SHMochaCoffe(){
        coffeName = "shanghai mocha";
    }
}
package com.study.design.Factory.factorymethod;

public class BJLatteCoffe extends Coffe{

    public BJLatteCoffe(){
        coffeName = "beijing latte";
    }
}
package com.study.design.Factory.factorymethod;

public class BJMochaCoffe extends Coffe{

    public BJMochaCoffe(){
        coffeName = "beijing mocha";
    }
}
package com.study.design.Factory.factorymethod;

public class SZLatteCoffe extends Coffe{

    public SZLatteCoffe(){
        coffeName = "shenzhen latte";
    }
}
package com.study.design.Factory.factorymethod;

public class SZMochaCoffe extends Coffe{

    public SZMochaCoffe(){
        coffeName = "shenzhen mocha";
    }

}    
package com.study.design.Factory.factorymethod;

/**
 * 咖啡店,现在它是个抽象类
 * 完成生产咖啡的所有工序,但是生产咖啡的具体口味由子类决定
 */
public abstract class CoffeStores {

    /**
     * 生产咖啡的工厂方法
     * @param type
     * @return
     */
    public Coffe productCoffe(int type){
        Coffe coffe = makeCoffe(type);
        box();
        return coffe;
    }

    /**
     * 打包
     */
    private void box(){
        System.out.println("packed……");
    }

    /**
     * 工厂方法
     * 生产咖啡的动作交由子类实现
     * @param type
     * @return
     */
    protected abstract Coffe makeCoffe(int type);
}
package com.study.design.Factory.factorymethod;

/**
 * 工厂类
 * 上海咖啡店
 */
public class SHCoffeStores extends BJCoffeStores {
    @Override
    protected Coffe makeCoffe(int type) {
        if (1 == type){
            return new SHMochaCoffe();
        }else{
            return new SHLatteCoffe();
        }
    }
}
package com.study.design.Factory.factorymethod;

public class BJCoffeStores extends CoffeStores{
    @Override
    protected Coffe makeCoffe(int type) {
        if (1 == type){
            return new BJMochaCoffe();
        }else {
            return new BJLatteCoffe();
        }
    }
}
package com.study.design.Factory.factorymethod;

public class SZCoffeStores extends CoffeStores{
    @Override
    protected Coffe makeCoffe(int type) {
        if (1 == type){
            return new SZMochaCoffe();
        }else{
            return new SZLatteCoffe();
        }
    }
}
package com.study.design.Factory.factorymethod;

public class SHConsumer {

    private CoffeStores coffeStores;

    public SHConsumer(CoffeStores coffeStores){
        this.coffeStores = coffeStores;
    }

    public void drink(int type){
        Coffe coffe = coffeStores.productCoffe(type);
        System.out.println("I got a cup of " + coffe.getCoffeName());
    }
}
package com.study.design.Factory.factorymethod;

public class BJConsumer {

    private CoffeStores coffeStores;

    public BJConsumer(CoffeStores coffeStores){
        this.coffeStores = coffeStores;
    }

    public void drink(int type){
        Coffe coffe = coffeStores.productCoffe(type);
        System.out.println("I got a cup of " + coffe.getCoffeName());
    }
}
package com.study.design.Factory.factorymethod;

public class SZConsumer {

    private CoffeStores coffeStores;

    public SZConsumer(CoffeStores coffeStores){
        this.coffeStores = coffeStores;
    }

    public void drink(int type){
        Coffe coffe = coffeStores.productCoffe(type);
        System.out.println("I got a cup of " + coffe.getCoffeName());
    }
}
package com.study.design.Factory.factorymethod;

public class FactoryMethodTest {

    public static void main(String[] args) {
        // 创建三个地区的咖啡厅实例
        SHCoffeStores shCoffeStores = new SHCoffeStores();
        BJCoffeStores bjCoffeStores = new BJCoffeStores();
        SZCoffeStores szCoffeStores = new SZCoffeStores();
        // 创建三个地区的消费者
        SHConsumer shConsumer = new SHConsumer(shCoffeStores);
        BJConsumer bjConsumer = new BJConsumer(bjCoffeStores);
        SZConsumer szConsumer = new SZConsumer(szCoffeStores);
        // 消费者消费各自地区的咖啡
        shConsumer.drink(1);
        bjConsumer.drink(2);
        szConsumer.drink(1);
    }
}

要点

  • 所谓工厂方法,就是有一个方法起到工厂创建对象的作用。这个方法定义为抽象的,依赖子类处理对象的创建。而在父类中又可以定义一些所有对象通用的行为,比如打包……。
  • 每个抽象方法的具体实现子类,又可以看做是一个简单工厂。一般只负责创建实例对象。
  • 使用者通过选择不同的子类来获取不同的对象

简单工厂与工厂方法模式的区别:

简单工厂把全部的事情,在一个地方都处理完了,而工厂方法却是创建一个框架,让子类决定如何实现具体对象的创建。简单工厂可以将对象创建出来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

当只有一个 SHCoffeStores 的时候,工厂方法模式有什么优点?

尽管只有一个具体创建者,工厂方法模式依然很有用,它帮助我们将产品的“实现”从“使用”中解耦。如果增加新的咖啡品种,CoffeStores 不会受到影响,因为 CoffeStores 与任何 SHCoffeStores 之间都不是紧耦合的。

                                WX 搜索-程序员个人修养

你可能感兴趣的:(java设计模式)