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

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

依赖倒置原则
要依赖抽象,不要依赖具体类
定义
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
如同定义中所说的,工厂方法让子类决定要实例化的类是哪一个。所谓的“决定”,并不是指模式允许子类本身再运行时做决定,而是指在编写创建者类时,不需要知道实际创建的产品是哪一个。选择了使用哪个子类,自然就决定了实际创建的产品是什么。
类图 设计模式——工厂方法模式
文章图片

代码实现 我们还是以上面咖啡店为例。
一个大的咖啡店不可能只有一个,而是遍布在全国各地,上海、北京、深圳……都会有分店。而且如果经营的好,分店还会增加。
那么,每个地区的分店虽然都是售卖咖啡,但是为了满足各地区客户的需求偏好,也会根据当地特色有些许的不同。比如上海人喜欢吃甜的,那么上海分店可能生产出来的同样的咖啡味道为偏甜,北京人口味偏咸和鲜,讲究浓,那么同样的咖啡口味就会更浓,深圳属于南方,口味清淡,那可能就会是原味咖啡居多,不放牛奶也不放糖,浓淡适中……
对于咖啡厅,从制作好咖啡到送到客户手中还需要一系列步骤,比如打包……,而这个打包的过程程序就与咖啡的类别没有太大关系。
下面我们用代码来实现:
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 搜索-程序员个人修养

    推荐阅读