2016-04-24 10:10:34

创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式

注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory) 

这三种模式从上到下逐步抽象,并且更具一般性。

而GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory),这是将简单工厂模式(Simple Factory)看成了工厂方法模式的一种特例,两者归为了一类。

工厂方法模式

(1)简单工厂模式(又叫静态工厂方法模式)

通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

模式中包含的角色及其职责:

1.工厂(Creator)角色
    简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。

2.抽象(Product)角色
    简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

3.具体产品(Concrete Product)角色
    简单工厂模式所创建的具体实例对象

例子:采集水果,如苹果、香蕉

Apple和Banana是具体产品角色;Fruit是抽象角色,是Apple和Banana的公共接口;FruitFactory是工厂角色,负责创建Apple和Banana实例。

public interface Fruit {
/*
* 采集
*/
public void get();
}
public class Apple implements Fruit{
/*
* 采集
*/
public void get(){
System.out.println("采集苹果");
}
}
public class Banana implements Fruit{
/*
* 采集
*/
public void get(){
System.out.println("采集香蕉");
}
public class FruitFactory {
/*
* 获得Apple类的实例
*/
public static Fruit getApple() {
return new Apple();
} /*
* 获得Banana类实例
*/
public static Fruit getBanana() {
return new Banana();
}
}
public class MainClass {
public static void main(String[] args) {
Fruit apple = FruitFactory.getApple();
Fruit banana = FruitFactory.getBanana();
apple.get();
banana.get();
}

还可以如下修改FruitFactory类

public class FruitFactory {
/*
* getFruit方法,获得所有产品对象
*/
public static Fruit getFruit(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Class fruit = Class.forName(type);
return (Fruit) fruit.newInstance();
}
}

这样动态的加载和创建Class类,但是没有注意大小写;

进一步修改为:

public class FruitFactory {
/*
* getFruit方法,获得所有产品对象
*/
public static Fruit getFruit(String type) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
if(type.equalsIgnoreCase("apple")) {
return Apple.class.newInstance();
} else if(type.equalsIgnoreCase("banana")) {
return Banana.class.newInstance();
} else {
System.out.println("找不到相应的实例化类");
return null;
}
}
}

然后

public class MainClass {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Fruit apple = FruitFactory.getFruit("Apple");
Fruit banana = FruitFactory.getFruit("Banana");
apple.get();
banana.get();
}
}

简单工厂模式的优缺点:

在这个模式中,工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。

不难发现,简单工厂模式的缺点也正体现在其工厂类上,由于工厂类集中了所有实例的创建逻辑,所以“高内聚”方面做的并不好。另外,当系统中的具体产品类不断增多时,可能会出现要求工厂类也要做相应的修改,扩展性并不很好。例如增加一种水果-梨子,需要在FruitFactory中继续增加else if语句,不符合开放封闭原则。这时候考虑下面的工厂方法模式。

(2)工厂方法模式(又叫多态工厂模式)

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

模式中包含的角色及其职责:

1.抽象工厂(Creator)角色
    工厂方法模式的核心,任何工厂类都必须实现这个接口。

2.具体工厂( Concrete 
Creator)角色
    具体工厂类是抽象工厂的一个实现,负责实例化产品对象。

3.抽象(Product)角色
    工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

4.具体产品(Concrete Product)角色
    工厂方法模式所创建的具体实例对象

例子:采集水果,如苹果、香蕉、梨子

Apple、Banana、Pear是具体产品角色;Fruit是抽象角色,是Apple、Banana、Pear的公共接口。他们的构造和前面简单工厂模式中一样。

AppleFactory、BananaFactory、PearFactory是具体工厂角色,负责创建Apple、Banana、Pear的实例;FruitFactory是抽象工厂角色,是AppleFactory、BananaFactory、PearFactory的公共接口。

public interface FruitFactory {
//水果厂
public Fruit getFruit(); }
public class AppleFactory implements FruitFactory {
//苹果厂,返回苹果实例
public Fruit getFruit() {
return new Apple();
}
}
public class BananaFactory implements FruitFactory {
//香蕉厂,返回香蕉实例
public Fruit getFruit() {
return new Banana();
}
}
public class PearFactory implements FruitFactory {
//梨子厂,返回梨子实例
public Fruit getFruit() {
return new Pear();
}
}
public class MainClass {
public static void main(String[] args) {
//获得AppleFactory
FruitFactory ff = new AppleFactory();
//通过AppleFactory来获得Apple实例对象
Fruit apple = ff.getApple();
apple.get(); //获得BananaFactory
FruitFactory ff2 = new BananaFactory();
//通过BananaFactory来获得Banana实例对象
Fruit banana = ff2.getBanana();
banana.get(); //获得PearFactory
FruitFactory ff3 = new PearFactory();
//通过PearFactory来获得Pear实例对象
Fruit pear = ff3.getPear();
pear.get();
}
}

和简单工厂模式比较:工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。

工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。

当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。工厂方法模式退化后可以演变成简单工厂模式。

抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

Apple、Pear属于产品等级结构;Apple又分南方Apple和北方Apple;Pear也分南方Pear和北方Pear。

一个工厂负责生产南方的Apple、Pear,这是一个产品族;一个工厂负责生产北方的Apple、Pear,这是另一个产品族。

模式中包含的角色及其职责:

1.抽象工厂(Creator)角色
抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。

2.具体工厂( Concrete  Creator)角色
具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。

3.抽象(Product)角色
抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

4.具体产品(Concrete Product)角色
抽象模式所创建的具体实例对象

注意:抽象工厂中方法对应产品结构,具体工厂对应产品族。

FruitFactory是抽象工厂角色,里面声明了苹果和梨子;SouthFactory和NorthFactory是具体工厂角色,SouthFactory返回南方苹果和梨子实例,NorthFactory返回北方苹果和梨子实例。

public interface Fruit {
/*
* 采集
*/
public void get();
}
public abstract class Apple implements Fruit{
/*
* 采集苹果
*/
public abstract void get();
}
public abstract class Pear implements Fruit{
/*
* 采集梨子
*/
public abstract void get();
}
public class SouthApple extends Apple {

    public void get() {
System.out.println("采集南方苹果");
} }
public class NorthApple extends Apple {

    public void get() {
System.out.println("采集北方苹果");
} }
public class SouthPear extends Pear {

    public void get() {
System.out.println("采集南方梨子");
} }
public class NorthPear extends Pear {

    public void get() {
System.out.println("采集北方梨子");
} }
public interface FruitFactory {
//实例化Apple
public Fruit getApple();
//实例化Pear
public Fruit getPear();
}
public class SouthFruitFactory implements FruitFactory {

    public Fruit getApple() {
return new SouthApple();
} public Fruit getPear() {
return new SouthPear();
} }
public class NorthFruitFactory implements FruitFactory {

    public Fruit getApple() {
return new NorthApple();
} public Fruit getPear() {
return new NorthPear();
} }
public class MainClass {
public static void main(String[] args) {
FruitFactory ff = new NorthFruitFactory();
Fruit apple = ff.getApple();
apple.get(); Fruit banana = ff.getPear();
pear.get(); FruitFactory ff2= new SouthFruitFactory();
Fruit apple2 = ff2.getApple();
apple2.get(); Fruit banana2 = ff2.getPear();
pear2.get();
}
}

如果再增加一个产品族:温室水果,包括温室苹果和温室梨子,只要增加相应的温室苹果类、温室梨子类和温室工厂类,符合“开放-封闭“”原则。但是若增加的是一个产品,如香蕉,则会违反该原则。

 补充:工厂模式在开发中的应用

一个简单的计算器(主要是加法运算):

OperationFactory是抽象工厂类,AddOperationFactory是具体工厂类;Operation是抽象角色类;AddOperation和SubtractionOperation是具体角色类。

public abstract class Operation {
private double num1;
private double num2; public double getNum1() {
return num1;
} public void setNum1(double num1) {
this.num1 = num1;
} public double getNum2() {
return num2;
} public void setNum2(double num2) {
this.num2 = num2;
} public abstract double getResult();
}
public class AddOperation extends Operation {

    public double getResult() {
double result = this.getNum1() + this.getNum2();
return result;
}
}
public class SubtractionOperation extends Operation {

    public double getResult() {
double result = this.getNum1() - this.getNum2();
return result;
} }
public interface OperationFactory {
public Operation getOperation();
}
public class AddOperationFactory implements OperationFactory{

    public Operation getOperation() {
return new AddOperation();
} }
import java.util.Scanner;

public class MainClass {
public static void main(String[] args) {
//1.接受控制台输入
System.out.println("---计算器程序---");
System.out.println("输入第一个操作数");
Scanner scanner = new Scanner(System.in);
String strNum1 = scanner.nextLine(); System.out.println("输入运算符");
String oper = scanner.nextLine(); System.out.println("输入第二个操作数");
String strNum2 = scanner.nextLine();
double result = 0;
double num1 = Double.parseDouble(strNum1);
double num2 = Double.parseDouble(strNum2); //2.进行运算
if("+".equals(oper)) {
OperationFactory factory = new AddOperationFactory();
Operation operation = factory.getOperation();
operation.setNum1(num1);
operation.setNum2(num2);
result = operation.getResult();
} //3.返回结果
System.out.println(strNum1 + oper + strNum2 + "=" + result);
}

java设计模式--创建型模式(一)的更多相关文章

  1. java设计模式--创建型模式--抽象工厂

    什么是抽象工厂,再次学习. 抽象工厂 概述 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 适用性 1.一个系统要独立于它的产品的创建.组合和表示时. 2.一个系统要由多个产品系 ...

  2. C#设计模式-创建型模式(转)

    一.简单工厂模式 简单工厂模式Simple Factory,又称静态工厂方法模式.它是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现. 优点: u 模式 ...

  3. C# 设计模式·创建型模式

    面试问到这个··答不出来就是没有架构能力···这里学习一下···面试的时候直接让我说出26种设计模式··当时就懵逼了··我记得好像之前看的时候是23种的 还有3个是啥的··· 这里先列出几种创建型模式 ...

  4. java设计模式5--原型模式(Prototype)

    本文地址:http://www.cnblogs.com/archimedes/p/java-prototype-pattern.html,转载请注明源地址. 原型模式 用原型实例指定创建对象的种类,并 ...

  5. Java设计模式——行为型模式

    行为型模式,共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 11种模式的关系: 第一类:通过父类与子类的关系 ...

  6. java设计模式--行为型模式--状态模式

    什么是行为型模式,小编觉得就是对行为的一种描述啦,一种对某种行为模型的定义. 状态模式: 状态模式 概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被 ...

  7. 设计模式-创建型模式,python享元模式 、python单例模式(7)

    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式. 享元模式尝 ...

  8. 设计模式----创建型模式之工厂模式(FactoryPattern)

    工厂模式主要分为三种简单工厂模式.工厂方法模式.抽象工厂模式三种.顾名思义,工厂主要是生产产品,作为顾客或者商家,我们不考虑工厂内部是怎么一个流程,我们要的是最终产品.将该种思路放在我们面向对象开发实 ...

  9. 【C#设计模式——创建型模式】简单工场模式

    进入码农行列也有一年半载了,仍然感觉自己混混沌沌,无所事事,无所作为,,,想想都下气,下气归下气,仍要奋起潜行,像愤怒的小鸟一边又一遍的冲向猪头也好,像蜗牛一样往前蹭也罢,总之要有蚂蚁啃骨头的精神!! ...

随机推荐

  1. 原生js实现选项卡

    html代码: <div class="tab"> <ul> <li class="selected">图片</li& ...

  2. nyoj1272表达式求值(递归法)

    递归写的,类似于之前的一道,但要更难一点,因为加入了'+','*'以及括号运算符,所以要考录周全: 这道题给了我很大启示,在第一道德基础上: 1!寻找括号的优先级,先找有没有不被任何括号夹住的加号,如 ...

  3. CodeForces 558B

    Description Amr has got a large array of size n. Amr doesn't like large arrays so he intends to make ...

  4. linux磁盘清理记录

    执行df -h查看自己的数据磁盘到达97% 使用du -h --max-depth=1  查看数据占用较大的文件 清理记录 1.mysql慢查询日志 # mv slow.log slow.log.ba ...

  5. OC 内存管理之自动内存管理ARC

    一.基本简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因 ...

  6. 解决mac更新系统后git无法使用

    这只是个小笔记啊,记着以后忘了可以再找出来,你们遇到了这个问题也可以翻出来看,废话不多说了,直接讲吧 一.无法使用的原因 mac  更新系统后  git命令无法使用,输入git命令会出现这样的提示 进 ...

  7. 信号的发送kill,raise,alarm,setitimer,abort,sigqueue

    1.kill函数 int kill(pid_t pid, int sig); 发送信号给指定的进程. (1) If pid is positive, then signal sig is sent t ...

  8. 利用padding-top/padding-bottom百分比,进行占位和高度自适应

    在css里面,padding-top,padding-bottom,margin-top,margin-bottom取值为百分比的时候,参照的是父元素的宽度. 比如:父元素宽度是100px, 子元素p ...

  9. C# 值类型与引用类型 (上)

    1. 主要内容 类型的基本概念 值类型深入 引用类型深入 值类型与引用类型的比较及应用 2. 基本概念 C#中,变量是值还是引用仅取决于其数据类型. C#的基本数据类型都以平台无关的方式来定义,C#的 ...

  10. (C/C++学习笔记) 十. 函数

    十. 函数 ● 基本概念 函数 函数定义 function definition: return_type function_name ( parameter list ) { Body of fun ...