Head First 设计模式 --4 工厂模式 抽象工厂模式
(用到了依赖倒置原则)
我们写的代码中,有的时候可能会出现根据外面给定的不同的参数在方法中根据参数实例化不同的实例,就是会根据不同的参数会new出不同的实例。如果这么写了,这段代码会非常的脆弱,一旦出现新的类型,那么就需要重写将这段代码找出来添加写的new。
之前说过针对接口编程,而不是针对实现。这句话也可以理解成,代码中尽量不要出现具体的实例。能用到实例的地方,应该用超类来代替,通过多态让代码走正确的分支。
通过例子来说明(看的就是《Head First 设计模式》这本书,所有还是用书中的例子)
不用工厂模式,我们就是这么写
Pizza orderPizza(String type){
Pizaa pizza;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} pizza.prepare();
pizza.bake();
//.........
}
通过工厂模式
Pizza orderPizza(String type) {
Pizza pizza = factory.createPizze("cheese"); pizza.prepare();
pizza.bake();
// ......... return pizza;
} class SimplePizzaFactory {
public Pizza createPizze(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
}
return pizza;
}
}
这么一看,我们似乎什么也没干,只是将代码搬到了另外一个地方。但是注意到,修改后的方法中,没有new,以后如果有新的类型的Pizza只需要修改这段代码就可以了,orderPizza的方法不用动。工厂模式就这么简单。还有另外一种类型的工厂模式,用静态方法返回实例对象,这种叫静态工厂。
class SimplePizzaFactory {
public static Pizza createCheesePizze() {
return new CheesePizza();
} public static Pizza createClamPizze() {
return new ClamPizza();
}
}
这就是工厂模式。其实工厂模式像是一种编程习惯。然后说一下抽象工厂模式。
抽象工厂模式的作用是建立一个产品家族的抽象类型,这个类型的子类定义了实例化实例的方法,想要获取实例,首先要实例这个类型的实例,在将这个实例传入某个工厂中。抽象工厂一般配合着工厂模式使用。抽象工厂的具体工厂通常用工厂方法创建。工厂模式的主要作用是创建类的实例,抽象工厂的作用是创建一系列的实例。
根据上面修改看一下抽象工厂的代码
interface Pizza {
public void prepare(); public void bake();
} class NSCheesePizza implements Pizza {
@Override
public void prepare() {} @Override
public void bake() {}
} class NSClamPizza implements Pizza {
@Override
public void prepare() {} @Override
public void bake() {}
} class ChicagoCheesePizza implements Pizza {
@Override
public void prepare() {} @Override
public void bake() {}
} class ChicagoClamPizza implements Pizza {
@Override
public void prepare() {} @Override
public void bake() {}
} abstract class PizzaStore { public Pizza orderPizza(String type) {
Pizza pizza = null;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
return pizza;
} abstract Pizza createPizza(String type);
} class NYPizzaStore extends PizzaStore {
@Override
Pizza createPizza(String type) {
if (type.equals("chesse")) {
return new NSCheesePizza();
} return null;
}
} class ChicagoPizzaStore extends PizzaStore {
@Override
Pizza createPizza(String type) {
if (type.equals("chesse")) {
return new ChicagoCheesePizza();
} return null;
}
}
public class Test {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
}
}
这里用到了依赖倒置原则。怎么倒置的,开始时需要制作不同的pizza,不同的具体类,这样所有的pizza店都会依赖这些具体类。于是,抽象出来了一个Pizza,这样就需要一个pizza工厂,然后所有的pizza类都依赖这样一个抽象,并且pizza店也需要这个抽象。这样我们就倒置了商店依赖具体pizza类的设计。
怎么才能避免违反依赖倒置原则:
1、变量不可以持有具体类的引用。(避免使用new)
2、不要让类派生具体类。
3、不要覆盖基类已经实现的方法。(如果覆盖了基类的方法,就说明这个类不是一个真正适合的抽象类)
Head First 设计模式 --4 工厂模式 抽象工厂模式的更多相关文章
- Java设计模式(三) 抽象工厂模式
原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...
- Java设计模式之-----工厂模式(简单工厂,抽象工厂)
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- <十一>读<<大话设计模式>>之抽象工厂模式
学习设计模式有一段时间了,对设计模式有一个体会,就是没那么难.就是设计程序遵循一些原则,让代码可复用,在改动的时候不用涉及太多的类,扩展方便.抽象工厂模式名字听起来抽象.但理解起来一点也不抽象,用语言 ...
- Java设计模式—工厂方法模式&抽象工厂模式
工厂方法模式与抽象工厂模式都是设计模式中重要而且常见的模式. 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法使一个类的实例化延迟到其子类. 通用类图如下: 在 ...
- PHP设计模式(三)抽象工厂模式(Abstract Factory)
一.什么是抽象工厂模式 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足以下条件: 系统中有多个产品族,而系统一次只可能消费其中一族产品. 同 ...
- Java设计模式学习笔记(四) 抽象工厂模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...
- Java的设计模式(4)--抽象工厂模式
提供一个创建一系列或相互依赖对象的接口,而无须指定他们具体的类.例如某些系统可能需要为用户提供一系列相关对象,但系统不希望用户直接使用new运算符实例化这些对象,而是应当由系统来控制这些对象的创建,否 ...
- 设计模式--简单工厂VS工厂VS抽象工厂
前几天我一直在准备大学毕业生,始终绑起来,如今,终于有时间去学习设计模式.我们研究今天的话题是植物三口之家的设计模式的控制--简单工厂VS工厂VS抽象工厂. 经过细心推敲,我们不难得出:工厂模式是简单 ...
- Head First设计模式——简单工厂、工厂、抽象工厂
前言:按照惯例我以Head First设计模式的工厂模式例子开始编码学习.并由简单工厂,工厂模式,抽象工厂模式依次演变,归纳他们的相同与不同. 话说Head First认为简单工厂并不是设计模式,而是 ...
- .Net简单工厂模式,工厂模式,抽象工厂模式实例
1.定义 简单工厂模式:是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 工厂模式:定义一个用于创建对象的接口, ...
随机推荐
- 安装LNMP之后出现 Access denied.解决方法
权限问题, 执行 sudo chown -R www:www /home/wwwroot
- Android-开发工具
jdk 当前版本 jdk-6u43-windows-x64 安装完成后,配置环境变量JAVA_HOME.Path adt-bundle 当前版本 adt-bundle-windows-x86_64 ...
- curl 查看一个web站点的响应时间(rt)
1. curl 查看web站点rt curl -o /dev/null -s -w %{time_namelookup}::%{time_connect}::%{time_starttransfer} ...
- oracle deterministic 关键字
多次看到DETERMINISTIC,一直很疑惑,今天做了一个实验.我们欺骗Oracle说是一个DETERMINISTIC函数,它在SQL中只调用一次.如果不使用DETERMINISTIC,可以看到出来 ...
- UE4 自定义物理表面类型(Surface Type)
如果想在UE4中实现在接触到不同物体表面时发出不同的声音或者效果时,比如人在不同的表面上速度会不同,子弹打到不同的表面时会出现不同的特效等,我们可以使用UE4中的表面类型来实现(Surface Typ ...
- 安装eclipse与pydev
按照此文档 最简单的eclipse安装方法 sudo apt-get install eclipse 弊端:因为ubuntu默认安装的不是最新版本的eclipse,所以你也不能安装最新的pydev. ...
- javascript jsscript .js xml html json soap
javascript ecma标准的脚本语言用于 jsscript 微软标准的一种脚本语言 .js javascript或jsscript保存成文件的形式可用于在html里重复引用 jsscript只 ...
- json学习小记
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 移动web前端之meta标签
最近这段时间忙着做web移动端,东西跟pc端还是有区别的.这个月也学到了不少东西,太多了就从头开始,先总结meta标签吧. 主要标签内容和注释如下: <meta charset="UT ...
- js页面刷新之实现定时刷新(定时器,meta)
测试页面的代码见上一篇博客 接下来进入正题-定时不断刷新页面的方法: 1.看到定时,很容易想到js的定时器: //第一种方法 //由于我们已经有了一个定时器,所以只要在定时器test中加入一句刷新页面 ...