Head First 设计模式 第4章工厂模式
第4章 工厂模式
在介绍工厂模式之前,先让我们来看一个例子。
这里有一个Pizza类,用来生产pizza,并返回对象,具体代码如下:
package com.ek.factory.simple; import com.ek.factory.Pizza;
import com.ek.factory.pizza.CheesePizza;
import com.ek.factory.pizza.GreekPizza;
import com.ek.factory.pizza.PepperoniPizza; /**
* @包名 com.ek.factory.simple
* @文件名 PizzaStore.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述
*/
public class PizzaStore { Pizza pizza;
public Pizza orderPizza(String type) { if (type.equals("cheese")) {
this.pizza = new CheesePizza();
}else if (type.equals("greek")) {
this.pizza = new GreekPizza();
}else if (type.equals("pepperoni")) {
this.pizza = new PepperoniPizza();
} this.pizza.prepare();
this.pizza.bake();
this.pizza.cut();
this.pizza.box(); return this.pizza;
}
}
这代码有什么问题呢?如果我在添加一种类型的pizza或者某种pizza卖的不好我想下架,这时候,我们就只能去修改PizzaStore这个类,当只有一个pizza商店的时候或许觉不出什么问题来,但是,当我们有好几个连锁店的时候,必须去修改每个PizzaStore类,这是有悖设计原则的,面向修改关闭,面向扩展开放。
那么我们接下来又该怎么修改呢?想一下,OO的设计原则(找出代码中需要变化的地方,将其独立出来,与不变的代码相分离,以便日后维护和扩展),接下我们对代码进行优化,进而得到了经过简单工厂模式设计之后的类图和代码,如下:
package com.ek.factory.simple; import com.ek.factory.Pizza;
import com.ek.factory.pizza.CheesePizza;
import com.ek.factory.pizza.GreekPizza;
import com.ek.factory.pizza.PepperoniPizza; /**
* @包名 com.ek.factory.simple
* @文件名 SimplePizzaFactory.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述 这是pizza的简单工厂
*/
public class SimplePizzaFactory { Pizza pizza; public Pizza createPizza(String type){
if (type.equals("cheese")) {
this.pizza = new CheesePizza();
}else if (type.equals("greek")) {
this.pizza = new GreekPizza();
}else if (type.equals("pepperoni")) {
this.pizza = new PepperoniPizza();
}
return this.pizza;
} }
package com.ek.factory.simple; import com.ek.factory.Pizza; /**
* @包名 com.ek.factory.simple
* @文件名 PizzaStore.java
* @作者 edi_kai
* @创建日期 2015年8月25日
* @版本 V 1.0
* @描述 这是修改后的PizzaStore
*/
public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) {
super();
this.factory = factory;
} public Pizza orderPizza(String type) { Pizza pizza = this.factory.createPizza(type); pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box(); return pizza;
}
}
这就是一个简单的工厂模式,简单工厂模式其实并不是一个设计模式,更像是一种编程习惯。
简单工厂模式算是最容易理解的工厂模式了,说完了简单工厂模式,让我们来分别看看它的两个延伸,工厂方法模式和抽象工厂模式。
在介绍模式之前,我们先来模拟一个需求场景,现在的汽车越来越多,那么汽车是怎么生产的呢?首先,你得有一个汽车生产工厂,然后,确定来生产什么牌子的汽车(国产车,美系车,德国车,韩系车)。不同的牌子需要由对应的工厂来生产汽车。
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)相同的产品族对应一个具体工厂,每级产品树中包含几颗树抽象工厂中就会存在几个创建方法;
总结:
工厂方法模式适用场景:产品比较单一,只有一级产品树的时候
抽象工厂模式适用场景:产品比较复杂,存在多级业务品种,业务分类的时候
再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的---看上面工厂方法模式跟抽象工厂模式的类图
设计到的新设计原则:
依赖倒置原则:尽量依赖抽象,不要依赖具体类
有错误的地方还请大家指出,大家共同学习,谢谢......
转载请注明出处
Head First 设计模式 第4章工厂模式的更多相关文章
- headfirst设计模式(5)—工厂模式体系分析及抽象工厂模式
先编一个这么久不写的理由 上周我终于鼓起勇气翻开了headfirst设计模式这本书,看看自己下一个设计模式要写个啥,然后,我终于知道我为啥这么久都没写设计模式了,headfirst的这个抽象工厂模式, ...
- java设计模式-----1、简单工厂模式
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单来说 ...
- Java设计模式(1)工厂模式(Factory模式)
工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...
- 设计模式之单例模式与工厂模式的Python实现(二)
2. 工厂模式 工厂模式是创建型设计模式的一种.核心的思想是,通过传递给类或函数某种产品的信息来创建产品并返回.当我们想得到产品a对象,只需把产品a的名字传递给工厂函数就能得到产品a对象.而核心思想的 ...
- [Python编程实战] 第一章 python的创建型设计模式1.1抽象工厂模式
注:关乎对象的创建方式的设计模式就是“创建型设计模式”(creational design pattern) 1.1 抽象工厂模式 “抽象工厂模式”(Abstract Factory Pattern) ...
- JAVA设计模式——第 5 章 工厂方法模式【Factory Method Pattern】(转)
女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了.这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风景太优美了,天空是湛蓝的,水是清澈的,空 ...
- 10月27日PHP加载类、设计模式(单例模式和工厂模式)、面向对象的六大原则
加载类可以使用include.require.require_once三种中的任意一种,每个关键字都有两种方法,但是这种方法的缺点是需要加载多少个php文件,就要写多少个加载类的方法.一般也就需要加载 ...
- Java设计模式2:简单工厂模式
简单工厂模式 简单工厂模式是类的创建模式,又叫做静态工厂方法模式.简单工厂模式由一个工厂对象决定生产出哪一种产品类的实例. 为什么要使用简单工厂模式 原因很简单:解耦. A对象如果要调用B对象,最简单 ...
- C#设计模式之二简单工厂模式(过渡模式)
一.引言 之所以写这个系列,是了为了自己更好的理解设计模式,也为新手提供一些帮助,我都是用最简单的.最生活化的实例来说明.在上一篇文章中讲解了单例模式,今天就给大家讲一个比较简单的模式--简单工厂模式 ...
随机推荐
- spring aop + xmemcached 配置service层缓存策略
Memcached 作用与使用 基本介绍 1,对于缓存的存取方式,简言之,就是以键值对的形式将数据保存在内存中.在日常业务中涉及的操作无非就是增删改查.加入缓存机制后,查询的时候,对数据进行缓存,增删 ...
- 【Android Developers Training】 23. 序言:保存数据
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 页面刷新vuex数据消失问题解决方案
VBox持续进行中,哀家苦啊,有没有谁给个star. vuex是vue用于数据存储的,和redux充当同样的角色. 最近在VBox开发的时候遇到的问题,页面刷新或者关闭浏览器再次打开的时候数据归零.这 ...
- Android各种Manager
一.PowerManager 主要是用来控制电源状态,设置屏幕状态,和电池待机状态 PowerManager pm = ((PowerManager)getSystemService(POWER_S ...
- 编写高质量代码改善程序的157个建议:第87个建议之区分WPF和WinForm的线程模型
今天有时间了,继续<编写高质量代码改善程序的157个建议>的阅读,当我阅读到建议87的时候,里面的一些代码示例和文中所说的不一致了,是不是我现在用的是NetFramework 4.0的缘故 ...
- Oracle的用户、角色以及权限相关操作
1.创建用户create user KD identified by 123456;2.授予连接数据库的权限grant connect to KD;3.将Scott用户的emp表授权给KD可以查询gr ...
- Linux之虚拟机网络配置
一般安装完虚拟机后,VMware会为虚拟机在网络连接配置为“NAT模式(N):用于共享主机的IP地址”. 这种模式下虚拟机会共享主机的网络环境,主机可以访问外网那么虚拟机可以,主机可以(哪怕是拨VPN ...
- 第三章:3.3 post 请求
1. 在 from表单中将 属性 methtod="post‘ 改变成post 2. 访问主页地址:http://localhost:8000/index 3. 以上出现的错误. 查资料发现 ...
- 64位win7安装jdk和eclipse
本人正确安装成功步骤,对他人可能无用: 1.直接拷以前32位eclipse ADT 2.安装32位的jdk:jdk-8u45-windows-i586 3.ok,所有环境变量无需手工设置 eclips ...
- CJOJ 1331 【HNOI2011】数学作业 / Luogu 3216 【HNOI2011】数学作业 / HYSBZ 2326 数学作业(递推,矩阵)
CJOJ 1331 [HNOI2011]数学作业 / Luogu 3216 [HNOI2011]数学作业 / HYSBZ 2326 数学作业(递推,矩阵) Description 小 C 数学成绩优异 ...