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 interfaceFruit {/** 采集*/
public voidget();
}
public class Apple implementsFruit{/** 采集*/
public voidget(){
System.out.println("采集苹果");
}
}
public class Banana implementsFruit{/** 采集*/
public voidget(){
System.out.println("采集香蕉");
}
public classFruitFactory {/** 获得Apple类的实例*/
public staticFruit getApple() {return newApple();
}/** 获得Banana类实例*/
public staticFruit getBanana() {return newBanana();
}
}
public classMainClass {public static voidmain(String[] args) {
Fruit apple=FruitFactory.getApple();
Fruit banana=FruitFactory.getBanana();
apple.get();
banana.get();
}
还可以如下修改FruitFactory类
public classFruitFactory {/** getFruit方法,获得所有产品对象*/
public static Fruit getFruit(String type) throwsInstantiationException, IllegalAccessException, ClassNotFoundException {
Class fruit=Class.forName(type);return(Fruit) fruit.newInstance();
}
}
这样动态的加载和创建Class类,但是没有注意大小写;
进一步修改为:
public classFruitFactory {/** getFruit方法,获得所有产品对象*/
public static Fruit getFruit(String type) throwsInstantiationException, 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 classMainClass {public static void main(String[] args) throwsInstantiationException, 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 interfaceFruitFactory {//水果厂
publicFruit getFruit();
}
public class AppleFactory implementsFruitFactory {//苹果厂,返回苹果实例
publicFruit getFruit() {return newApple();
}
}
public class BananaFactory implementsFruitFactory {//香蕉厂,返回香蕉实例
publicFruit getFruit() {return newBanana();
}
}
public class PearFactory implementsFruitFactory {//梨子厂,返回梨子实例
publicFruit getFruit() {return newPear();
}
}
public classMainClass {public static voidmain(String[] args) {//获得AppleFactory
FruitFactory ff = newAppleFactory();//通过AppleFactory来获得Apple实例对象
Fruit apple =ff.getApple();
apple.get();//获得BananaFactory
FruitFactory ff2 = newBananaFactory();//通过BananaFactory来获得Banana实例对象
Fruit banana =ff2.getBanana();
banana.get();//获得PearFactory
FruitFactory ff3 = newPearFactory();//通过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 interfaceFruit {/** 采集*/
public voidget();
}
public abstract class Apple implementsFruit{/** 采集苹果*/
public abstract voidget();
}
public abstract class Pear implementsFruit{/** 采集梨子*/
public abstract voidget();
}
public class SouthApple extendsApple {public voidget() {
System.out.println("采集南方苹果");
}
}
public class NorthApple extendsApple {public voidget() {
System.out.println("采集北方苹果");
}
}
public class SouthPear extendsPear {public voidget() {
System.out.println("采集南方梨子");
}
}
public class NorthPear extendsPear {public voidget() {
System.out.println("采集北方梨子");
}
}
public interfaceFruitFactory {//实例化Apple
publicFruit getApple();//实例化Pear
publicFruit getPear();
}
public class SouthFruitFactory implementsFruitFactory {publicFruit getApple() {return newSouthApple();
}publicFruit getPear() {return newSouthPear();
}
}
public class NorthFruitFactory implementsFruitFactory {publicFruit getApple() {return newNorthApple();
}publicFruit getPear() {return newNorthPear();
}
}
public classMainClass {public static voidmain(String[] args) {
FruitFactory ff= newNorthFruitFactory();
Fruit apple=ff.getApple();
apple.get();
Fruit banana=ff.getPear();
pear.get();
FruitFactory ff2= newSouthFruitFactory();
Fruit apple2=ff2.getApple();
apple2.get();
Fruit banana2=ff2.getPear();
pear2.get();
}
}
如果再增加一个产品族:温室水果,包括温室苹果和温室梨子,只要增加相应的温室苹果类、温室梨子类和温室工厂类,符合“开放-封闭“”原则。但是若增加的是一个产品,如香蕉,则会违反该原则。
补充:工厂模式在开发中的应用
一个简单的计算器(主要是加法运算):
OperationFactory是抽象工厂类,AddOperationFactory是具体工厂类;Operation是抽象角色类;AddOperation和SubtractionOperation是具体角色类。
public abstract classOperation {private doublenum1;private doublenum2;public doublegetNum1() {returnnum1;
}public void setNum1(doublenum1) {this.num1 =num1;
}public doublegetNum2() {returnnum2;
}public void setNum2(doublenum2) {this.num2 =num2;
}public abstract doublegetResult();
}
public class AddOperation extendsOperation {public doublegetResult() {double result = this.getNum1() + this.getNum2();returnresult;
}
}
public class SubtractionOperation extendsOperation {public doublegetResult() {double result = this.getNum1() - this.getNum2();returnresult;
}
}
public interfaceOperationFactory {publicOperation getOperation();
}
public class AddOperationFactory implementsOperationFactory{publicOperation getOperation() {return newAddOperation();
}
}
importjava.util.Scanner;public classMainClass {public static voidmain(String[] args) {//1.接受控制台输入
System.out.println("---计算器程序---");
System.out.println("输入第一个操作数");
Scanner scanner= newScanner(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= newAddOperationFactory();
Operation operation=factory.getOperation();
operation.setNum1(num1);
operation.setNum2(num2);
result=operation.getResult();
}//3.返回结果
System.out.println(strNum1 + oper + strNum2 + "=" +result);
}