java设计模式--创建型模式(一)
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); }