[img][/img]说工厂方法模式前先说下简单工厂模式吧!
按照设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,学习了此模式可以为后面的很多中模式打下基础。那好,我们就来了解下什么是简单工厂模式?
意图:根据提供给他的数据,返回几个可能类中的一个类的实例。
例如:我再一次带MM光临了麦当劳时,这次MM不想吃鸡翅了,而是选择了吃汉堡,可见这个时候ChickenFactory无法满足客户需要了,需要做出更改,方法就是再加一个工厂类:HamburgerFactory该类负责创建汉堡系列产品,这种方法造成的直接结果就是每一种产品都需要一个具体的工厂类,造成工厂过多,客户端使用不方便,因为我带MM去麦当劳不能由MM或者我决定鸡翅和汉堡是怎么生产出来的,我们只需要跟服务员说一声吃什么就可以了。 而工厂方法模式正是解决这种弊端而出现的,在工厂方法模式里,由一个抽象工厂类负责所有产品的创建,工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。
不多废话了,我还是喜欢从代码入手。
首先让大家看一个比较经典的简单工厂例子
package garden;
/**
* 苹果
*
* 由于苹果是多年生植物,因此多出一个treeAge 性质,
* 描述苹果树的树龄
*
*/
public class Apple implements Fruit {
private int treeAge;
// 生长
public void grow() {
log("Apple is growing...");
}
// 收获
public void harvest() {
log("Apple has been harvested.");
}
// 种植
public void plant() {
log("Apple has been planted.");
}
// 辅助方法
public static void log(String msg) {
System.out.println(msg);
}
// 树龄的取值方法
public int getTreeAge() {
return treeAge;
}
// 树龄的赋值方法
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
package garden;
/**
* 苹果
*
* 由于苹果是多年生植物,因此多出一个treeAge 性质,
* 描述苹果树的树龄
*
*/
public class Apple implements Fruit {
private int treeAge;
// 生长
public void grow() {
log("Apple is growing...");
}
// 收获
public void harvest() {
log("Apple has been harvested.");
}
// 种植
public void plant() {
log("Apple has been planted.");
}
// 辅助方法
public static void log(String msg) {
System.out.println(msg);
}
// 树龄的取值方法
public int getTreeAge() {
return treeAge;
}
// 树龄的赋值方法
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
package garden;
/**
* 葡萄
*
* 但由于葡萄分有籽和无籽两种,因此,比通常的水果多出一个seedless 性质
*
*/
public class Grape implements Fruit {
private boolean seedless;
// 生长
public void grow() {
log("Grape is growing...");
}
// 收获
public void harvest() {
log("Grape has been harvested.");
}
// 种植
public void plant() {
log("Grape has been planted.");
}
// 辅助方法
public static void log(String msg) {
System.out.println(msg);
}
// 有无籽的取值方法
public boolean getSeedless() {
return seedless;
}
// 有无籽的赋值方法
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
package garden;
/**
* 草莓
*
* Strawberry 类实现了Fruit 接口,因此,也是水果类型的子类型
*/
public class Strawberry implements Fruit {
// 生长
public void grow() {
log("Strawberry is growing...");
}
// 收获
public void harvest() {
log("Strawberry has been harvested.");
}
// 种植
public void plant() {
log("Strawberry has been planted.");
}
// 辅助方法
public static void log(String msg) {
System.out.println(msg);
}
}
package garden;
/**
* 当没有此类水果所抛出的一次
*
*/
public class BadFruitException extends Exception {
private static final long serialVersionUID = 3677167960651698463L;
public BadFruitException(String msg) {
super(msg);
}
}
package garden;
/**
* 农场的园丁
*
* FruitGardener 类会根据客户端的要求,创建出不同的水果对象,比如苹果(Apple),
* 葡萄(Grape)或草莓(Strawberry)的实例。而如果接到不合法的要求, FruitGardener 类会抛出BadFruitException
* 异常
*
*/
public class FruitGardener {
// 静态工厂方法
public static Fruit factory(String which) throws BadFruitException {
if (which.equalsIgnoreCase("apple")) {
return new Apple();
} else if (which.equalsIgnoreCase("strawberry")) {
return new Strawberry();
} else if (which.equalsIgnoreCase("grape")) {
return new Grape();
}else {
throw new BadFruitException("Bad fruit request");
}
}
}
package garden;
/**
* 这样就可以种各种水果了
*
*/
public class Run {
public static void main(String[] args) {
try {
// 种植葡萄
FruitGardener.factory("grape").plant();
FruitGardener.factory("grape").grow();
FruitGardener.factory("grape").harvest();
System.out.println("==================================");
// 种植苹果
FruitGardener.factory("apple").plant();
FruitGardener.factory("apple").grow();
FruitGardener.factory("apple").harvest();
System.out.println("==================================");
// 种植草莓
FruitGardener.factory("strawberry").plant();
FruitGardener.factory("strawberry").grow();
FruitGardener.factory("strawberry").harvest();
System.out.println("==================================");
}
catch (BadFruitException e) {
}
}
}
具体实现可看garden包,在factory-pattern 文件中
由于接下来代码过多我就不一一贴出来,全部已经打包放在factory2-pattern文件中了
敬请谅解。
下面通过一个例子说说简单工厂模式和工厂方法模式。
这些例子的都是来自现实的一个比萨店,由于比萨店每天需要为客户提供不同种比萨原型
然而现在该点已经在负责切、烤、烘等操作了,现在如果有人需要一种CheesePizza,如果该点还要从原材料开始先磨出比萨原型,再通过各种加工未免会出现过程太久让顾客等的不耐烦,而且该店如果负责的 工序太多,也容易出现差错。于是乎,该店决定让比萨工厂专门负责提供比萨原型的饼,然后在通过自己加工就可以个顾客了
/**
* 披萨店
* 用简单工厂模式
*
* 特点:主要让工厂负责生产所有类型的披萨,针对接口编程
*
* 优点:针对接口编程可以隔离掉以后系统可能发生的一大堆改变
* 方法简单易理解,思路清晰
* 缺点:不易管理,当子类增删改后得同时维护工厂类导致耦合性太强
* 违背开闭原则即扩展开发修改关闭
*
* 说明:简单的工厂其实不只是一个设计模式,反而比较像一种编程习惯。
* 但不要因为他不是一个模式就忽略的他的用途
*/
具体代码看附件 simple_factory包
接下来由于这个点开大了,他们现在不同的地区开加盟店了,而且不同地方的加盟店在原店味道大体不变的情况下他们还有一些自己地方的特色或者说加入一些改良,如果还是按照简单工厂方法来设计的话,或许你会觉得每次我有新品种的比萨产生或者销量不好的比萨给淘汰了,都需要修改原工厂类,这样大家会感觉等到比萨品种一变多就很难维护。所以在此作者就推荐了一种工厂方法的模式设计,让自己地方的比萨自己维护字的的,这样具体的类型就有分店决定,就不至于耦合性太强了,也不用让总部关系具体的类型,减少错误,这样也符合倒置依赖原则。
其实这也符合做人的道理,大家玩玩会看到做官或做领导的说话都是很笼统很抽象的,如果太具体了难免会出差错。
接下去还是看具体代码吧!
/**
* 披萨店
* 用工厂方法模式
*
* 定义:定义了一个创建对象接口,单由子类决定要实例化的类时哪一个。
* 让类把实例化推迟到子类
*
* 特点:让已有一个PizzaStore做为超类
* 让每域类型都继承这个类,这样每个子类各种决定如何做比萨
*
* 优点:降低代码耦合性,符合倒置依赖原则。
* 简单工厂把全部事情在一个地方处理完,然而工厂方法却是创建一个框架,
* 让子类如何实现
*
* 适用场合:
* 需要客户代码从需要实例化的具体类中解耦。或者如果你目前还不知道将来需要实例化那些具体类时。
*
*
*/
具体例子实现看附件factory_method包
在实际生活中,如果你让一个工厂通过原始材料如果做个原型的饼可能需要的原材料是大米、小麦、猪肉、牛肉……一些产品。然而在实际生活中,许多工厂喜欢偷工减料,所以为了杜绝这种现象的发生往往需要按照总部要求制作的原料工厂开在地方,这些原料工厂专门把如做好的火腿肠给他们,而不是仅仅提供肉和面粉本身。在实现这些原料工厂时他们一定要严格符合总部指定的要求制作,且总部已经为各种这些原料的实现提供模版了。
/**
* 披萨店 -- 抽象工厂模式
* 用工厂方法模式--没看错抽象工厂模式中确实用到了工厂方法模式
*
* 定义:提供一个接口,用于创建相关或依赖对象家族
* 而不需要确定具体类
*
* 特点:抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道
* 或关心实际产出的具体产品是什么也即由子类定义了产品被产生的方法。
* 这样依赖,客户就从具体的产品中被解耦。
* 本例子中就是大家只需要关心所提供的材料,而不需要知道此材料的原材料
* 如提供香肠而不用关心香肠是用什么做成的
*
* 缺点:如果加入新产品就必须改变接口(这点工厂方法做的比较好),因为它是创建一个
* 家族的产品所有需要一个大接口
*
* 与工厂方法的不同点:
* 1.抽:对象。工厂:类
* 2.抽:通过组合创建对象。工厂:通过继承并覆盖他的方法,而是让子类创建对象(这样子类决定类型)
* 3.抽: 加入新产品必须改变接口. 工厂:只需要改变子类的实现即可
* 4.抽: 用来创建一个家族。工厂:创建一个产品
*
* 与工厂方法相同点:
* 1.都可以从具体产品中解耦,可以把一群相关的产品集合起来
*
* 适用场合:
* 当你需要创建产品家族和想让制造的相关产品集合起来时
*/
具体代码实现看附件abstract_factory包
分享到:
相关推荐
JAVA设计模式-day2,请的行业大能讲得课程,涉及:创建模式(5种: 1、 工厂方法模式(Factory Method); 2、 抽象工厂模式; 3、 单例模式(Singleton) • 4、 建造者模式(Builder); 5、 原型模式(Prototype...
**简单工厂模式**是软件设计模式中的一种基础模式,它属于创建型模式,主要用于简化对象的创建过程。在简单工厂模式中,一个专门的工厂类负责创建对象,客户端通过调用工厂类的方法来获取所需的对象,而无需关心具体...
《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...
《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...
《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...
在描述中提到的"第八讲 设计模式( I )"中,提到了设计模式的三个主要元素:背景、问题和解决方案。背景是指适合应用设计模式的场景,问题是在这个背景下需要解决的关键挑战,而解决方案则是设计模式提供的经典设计...
工厂方法模式是设计模式中的创建型模式,它在软件工程中扮演着重要的角色,尤其对于初学者来说,理解和掌握这一模式对于提升编程能力和设计能力大有裨益。在这个主题中,我们将深入探讨工厂方法模式的核心概念、作用...
所有的设计模式Java实现。 第一讲:简单工厂模式 第二讲:工厂方法模式 第三讲:抽象工厂模式 第四讲:工厂模式在开发中的运用 第五讲:单例模式 第六讲:原型模式 ...第三十讲:设计模式总结
01第一讲简单工厂模式 02第二讲工厂方法模式 03第三讲抽象工厂模式 04第四讲工厂模式在开发中的运用 05第五讲单例模式 06第六讲原型模式 07第七讲建造者模式 08第八讲装饰模式 09第九讲策略模式 10第十讲观察者模式 ...
设计模式捕获了随时间进化与发展的问题的求解方法,因此它们并不是人们从一开始就采用的设计方案。它们反映了不为人知的重新设计和重新编码的成果,而这些都来自软件开发者为了设计出灵活可复用的软件而长时间进行的...
在软件设计模式中,工厂方法模式(Factory Method Pattern)是一种创建型模式,它提供了一种创建对象的最佳方式。本讲将深入探讨工厂方法模式的概念、结构以及在实际开发中的应用。 工厂方法模式的核心思想是定义一...
Java设计模式是软件开发中的重要概念,它们是解决常见...这个压缩包资料“[浪曦原创]JAVA设计模式 第2讲 单态模式和简单工厂模式(jzkangta)”应包含了详细的讲解和示例代码,可以帮助深入理解和应用这两种设计模式。
### 设计模式概述 设计模式是在软件开发过程中,为了解决特定问题而形成的标准化解决方案。它们代表了在软件工程领域经过验证的最佳实践,能够帮助开发者更高效地解决常见问题,并提高代码的可读性、可复用性和可...
这个“设计模式(讲的最详细版本)”的资源很可能包含了对23种经典GOF(Gang of Four)设计模式的深入解释,以及可能还包括了一些现代编程环境中的新设计模式。 1. **创建型模式**:这类模式主要关注对象的创建过程,...
### 设计模式与抽象工厂设计模式详解 #### 模式的起源与定义 设计模式的概念源自建筑领域,由克里斯多佛·亚历山大提出。他通过对建筑物、城镇、街道等结构的研究,发现了优秀的结构设计之间存在着共性。亚历山大...
共150讲,时长共 33...1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括...
书中首先从OOP 采用的机制—— 抽象类、接口、契约式编程开始讲起,然后介绍了静态方法、单例模式、工厂模式和PHP 6 的新特性等内容,接着介绍了测试和文档方面的内容,还介绍了标准PHP 库SPL 方面的知识以及PHP ...