Head First 设计模式 第4章工厂模式

第4章 工厂模式

  在介绍工厂模式之前,先让我们来看一个例子。

  这里有一个Pizza类,用来生产pizza,并返回对象,具体代码如下:

 1 package com.ek.factory.simple;
 2 
 3 import com.ek.factory.Pizza;
 4 import com.ek.factory.pizza.CheesePizza;
 5 import com.ek.factory.pizza.GreekPizza;
 6 import com.ek.factory.pizza.PepperoniPizza;
 7 
 8 /**
 9  * @包名   com.ek.factory.simple
10  * @文件名 PizzaStore.java
11  * @作者   edi_kai
12  * @创建日期 2015年8月25日
13  * @版本 V 1.0
14  * @描述
15  */
16 public class PizzaStore {
17 
18     Pizza pizza;
19     public Pizza orderPizza(String type) {
20         
21         if (type.equals("cheese")) {
22             this.pizza = new CheesePizza();
23         }else if (type.equals("greek")) {
24             this.pizza = new GreekPizza();
25         }else if (type.equals("pepperoni")) {
26             this.pizza = new PepperoniPizza();
27         }
28         
29         this.pizza.prepare();
30         this.pizza.bake();
31         this.pizza.cut();
32         this.pizza.box();
33         
34         return this.pizza;
35     }
36 }

  这代码有什么问题呢?如果我在添加一种类型的pizza或者某种pizza卖的不好我想下架,这时候,我们就只能去修改PizzaStore这个类,当只有一个pizza商店的时候或许觉不出什么问题来,但是,当我们有好几个连锁店的时候,必须去修改每个PizzaStore类,这是有悖设计原则的,面向修改关闭,面向扩展开放。

  那么我们接下来又该怎么修改呢?想一下,OO的设计原则(找出代码中需要变化的地方,将其独立出来,与不变的代码相分离,以便日后维护和扩展),接下我们对代码进行优化,进而得到了经过简单工厂模式设计之后的类图和代码,如下:

 1 package com.ek.factory.simple;
 2 
 3 import com.ek.factory.Pizza;
 4 import com.ek.factory.pizza.CheesePizza;
 5 import com.ek.factory.pizza.GreekPizza;
 6 import com.ek.factory.pizza.PepperoniPizza;
 7 
 8 /**
 9  * @包名   com.ek.factory.simple
10  * @文件名 SimplePizzaFactory.java
11  * @作者   edi_kai
12  * @创建日期 2015年8月25日
13  * @版本 V 1.0
14  * @描述 这是pizza的简单工厂
15  */
16 public class SimplePizzaFactory {
17 
18     Pizza pizza;
19     
20     public Pizza createPizza(String type){
21         if (type.equals("cheese")) {
22             this.pizza = new CheesePizza();
23         }else if (type.equals("greek")) {
24             this.pizza = new GreekPizza();
25         }else if (type.equals("pepperoni")) {
26             this.pizza = new PepperoniPizza();
27         }
28         return this.pizza;
29     }
30     
31 }

 

 1 package com.ek.factory.simple;
 2 
 3 import com.ek.factory.Pizza;
 4 
 5 /**
 6  * @包名   com.ek.factory.simple
 7  * @文件名 PizzaStore.java
 8  * @作者   edi_kai
 9  * @创建日期 2015年8月25日
10  * @版本 V 1.0
11  * @描述  这是修改后的PizzaStore 
12  */
13 public class PizzaStore {
14 
15     SimplePizzaFactory factory;
16     
17     public PizzaStore(SimplePizzaFactory factory) {
18         super();
19         this.factory = factory;
20     }
21 
22     public Pizza orderPizza(String type) {
23         
24         Pizza pizza = this.factory.createPizza(type);
25         
26         pizza.prepare();
27         pizza.bake();
28         pizza.cut();
29         pizza.box();
30         
31         return pizza;
32     }
33 }

  这就是一个简单的工厂模式,简单工厂模式其实并不是一个设计模式,更像是一种编程习惯

  简单工厂模式算是最容易理解的工厂模式了,说完了简单工厂模式,让我们来分别看看它的两个延伸,工厂方法模式和抽象工厂模式。

  在介绍模式之前,我们先来模拟一个需求场景,现在的汽车越来越多,那么汽车是怎么生产的呢?首先,你得有一个汽车生产工厂,然后,确定来生产什么牌子的汽车(国产车,美系车,德国车,韩系车)。不同的牌子需要由对应的工厂来生产汽车。

  1丶工厂方法模式

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

    工厂模式对应的类图如下

  类图对应的代码如下:

/** 
 * Project Name: head first 
 * File Name: CarFactory.java 
 * Package Name: com.ek.factory_2 
 * Reason: 抽象工厂
 * Date: 2015年9月7日上午12:19:10 
 * Copyright (c) 2015, edi_kai All Rights Reserved. 
 * @author: edi_kai
 * @version: v1.1
 * @since: JDK 1.7 
*/ 
package com.ek.factory_2;

import com.ek.factory_2.product.Car;

public interface CarFactory {
    Car createCar(String type);
}
/** 
 * Project Name: head first 
 * File Name: ChineseCarFactory.java 
 * Package Name: com.ek.factory_2 
 * Reason: 具体工厂-国产车.
 * Date: 2015年9月7日上午12:24:20 
 * Copyright (c) 2015, edi_kai All Rights Reserved. 
 * @author: edi_kai
 * @version: v1.1
 * @since: JDK 1.7 
*/ 
package com.ek.factory_2;

import com.ek.factory_2.product.Car;
import com.ek.factory_2.product.NormalCarBorui;
import com.ek.factory_2.product.SUVCarBYDsong;

public class ChineseCarFactory implements CarFactory {

    @Override
    public Car createCar(String type) {
        
        if ("borui".equalsIgnoreCase(type)) {
            return new NormalCarBorui();
        }else if ("song".equalsIgnoreCase(type)) {
            return new SUVCarBYDsong();
        }
        
        return null;
    }

}
/** 
 * Project Name: head first 
 * File Name: KoreaCarFactory.java 
 * Package Name: com.ek.factory_2 
 * Reason: 具体工厂-韩系车.
 * Date: 2015年9月7日上午12:28:08 
 * Copyright (c) 2015, edi_kai All Rights Reserved. 
 * @author: edi_kai
 * @version: v1.1
 * @since: JDK 1.7 
*/ 
package com.ek.factory_2;

import com.ek.factory_2.product.Car;
import com.ek.factory_2.product.NormalCarELartra;
import com.ek.factory_2.product.NormalCarSonata;

public class KoreaCarFactory implements CarFactory {

    @Override
    public Car createCar(String type) {
        
        if ("sonata".equalsIgnoreCase(type)) {
            return new NormalCarSonata();
        }else if ("elartra".equalsIgnoreCase(type)) {
            return new NormalCarELartra();
        }
        
        return null;
    }

}
/** 
 * Project Name: head first 
 * File Name: Main.java 
 * Package Name: com.ek.factory_2.main 
 * Reason: 测试代码.
 * Date: 2015年9月7日上午12:31:42 
 * Copyright (c) 2015, edi_kai All Rights Reserved. 
 * @author: edi_kai
 * @version: v1.1
 * @since: JDK 1.7 
*/ 
package com.ek.factory_2.main;

import com.ek.factory_2.CarFactory;
import com.ek.factory_2.ChineseCarFactory;
import com.ek.factory_2.KoreaCarFactory;
import com.ek.factory_2.product.Car;

public class Main {

    public static void main(String[] args) {
        CarFactory ccf = new ChineseCarFactory();
        Car song = ccf.createCar("song");
        
        CarFactory kcf = new KoreaCarFactory();
        Car sonata = kcf.createCar("sonata");
        
        song.getName();
        song.getBrand();
        song.getColor();
        
        sonata.getName();
        sonata.getBrand();
        sonata.getColor();
    }
    
}

 

    工厂方法模式的特点:

      1)针对统一个产品等级,不存在父子级关系(看一下抽象工厂模式的类图即可明白);

      2)只有一个抽象产品类,所有的产品都实现/继承自该抽象类(Car);

      3)所有的具体产品类按具体的工厂类分类,当需要添加新类别的产品时,只需要添加一个具体工厂类即可(如类图中,Sonata属于韩系车,添加KoreaCarFactory实现    CarFactory即可),易于扩展,并完全符合开闭原则的!;

    工厂方法模式总结:

      工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的(就如同下面我们要    说的场景)。那么这种情况下就可能需要使用抽象工厂模式了。

  现在需求改变了,不仅需要按照国家来生产汽车,还要按照用途来生产(私家轿车/SUV/MPV/货车);这个需求中汽车出现了多级产品树,如果在继续使用工厂方法模式会有大量的代码,不利于后期维护,所以,这个时候我们就应该想到抽象工厂模式,来解决这个问题。

  2丶抽象工厂模式

    抽象工厂模式定义:抽象一个接口用来创建相关或依赖对象的家族,而不需要明确指定具体类。

    产品族:具体定义我也不是很清楚,但是类图中的NormalCarBorui(吉利博瑞汽车)跟SUVCarBYDsong SUVCarCS75是同一产品族;

    产品树:SUVCcar PMVCar是同一级产品树

    抽象工厂模式的特点:

      1)针对的是面向多个产品等级结构;

      2)一个抽象工厂类,可以派生出多个具体工厂类

      3)相同的产品族对应一个具体工厂,每级产品树中包含几颗树抽象工厂中就会存在几个创建方法;

    总结:

      工厂方法模式适用场景:产品比较单一,只有一级产品树的时候

      抽象工厂模式适用场景:产品比较复杂,存在多级业务品种,业务分类的时候

      再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的---看上面工厂方法模式跟抽象工厂模式的类图

   

  设计到的新设计原则:

    依赖倒置原则:尽量依赖抽象,不要依赖具体类

 

  有错误的地方还请大家指出,大家共同学习,谢谢......

 

  转载请注明出处

转载于:https://www.cnblogs.com/edi-kai/p/4757714.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值