工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。
工厂模式有3种形态:
1.简单工厂模式(静态方法模式)。
2.工厂方法模式(多态性工厂,虚拟构造子模式)。
3.抽象工厂(工具箱模式)。
它们按照使用的范围和抽象程度从高到低:抽象工厂模式>=工厂方法模式>简单工厂模式
简单工程模式(又称静态工厂方法模式)是类的创建模式,是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一种特殊实现。
简单工厂模式的一般性结构:
简单工厂模式的类图:
简单工厂模式设计的3个角色:
1.工厂类角色(Creator):担任这个角色的时工厂方法模式的核心。该类在客户端的直接调用下创建产品对象,它往往由一个具体类实现。
2.抽象产品角色(Product):担任这个角色的类是由工厂方法模式所创建的对象的父类或者它们共同拥有的接口。抽象产品角色可以用一个接口或者抽象类实现。
3.具体产品角色(Concrete Product):工厂方法模式所创建的人任何对象都是这个角色的实例,具体产品角色由一个具体类实现。
简单工厂模式的优缺点:
优点:
核心是工厂类。该类还有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。而客户端则可以避免直接创建产品对象,而仅仅是负责消费产品,通过这种做法实现了对责任的分割。
缺点:
1.工厂类是整个模式的核心,一旦该类出问题,整个系统都会受到影响。
2.缺乏灵活,当出现新的接口等新需求时,进行功能扩展比较麻烦。
3.静态方法无法由子类继承,无法形成基于继承的等级结构。
示例:
到自动贩卖机中,我们投币选择饮料,然后饮料就会根据你的选择掉出来。
饮料接口(抽象产品):
/** * 饮料 */ public interface Drink { public void taste(); }作为饮料的抽象接口,要有需要的所有饮料的属性和方法,然后我们的具体饮料产品可以实现该接口的功能。
具体产品类:
具体的饮料产品,实现饮料接口,实现各自的方法,拥有不同的表现形式。
可乐:
/** * 可乐 */ public class Cola implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->可乐 酸甜味"); } }雪碧:
/** * 雪碧 */ public class Sprite implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->雪碧 柠檬味"); } }自动贩卖机(工厂类):
/** * 自动贩卖机 */ public class VendingMachine { // 工厂核心(静态方法):返回具体的饮料对象 public static Drink factory(int type) { Drink drink; switch (type) { case 0: drink = new Cola(); break; case 1: drink = new Sprite(); break; default: drink = null; break; } return drink; } }自动贩卖机中是工厂模式的核心类,我们调用该类的静态工厂方法,就会返回具体的产品对象。
测试类:
public class Main { public static void main(String[] args) { Drink fruit; fruit=VendingMachine.factory(0); fruit.taste(); fruit=VendingMachine.factory(1); fruit.taste(); } }
对整个系统而言,工厂模式把具体的创建对象的细节包装和隐藏了起来,具体的实现在工厂类中实现,外界只需调用静态工厂方法,就会得到具体的产品实例。
使用范围:
当产品的类型一定定义好不会被修改,所有的产品具有同样的特性可以抽离出公共接口时使用。
工厂方法模式(虚拟构造子模式,多态性工厂模式)是类的创建模式,用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
工厂方法模式的一般性结构:
工厂方法模式的类图:
工厂方法模式中的4个角色:
抽象工厂角色(Creator):担任这个角色的时工厂方法模式的核心,任何在模式中创建对象的工厂类必须实现该接口。
具体工厂角色(Concrete Creator):担任这个角色的时实现了抽象工厂接口的具体类,具体工厂角色含有与应用相关的逻辑,并且受到应用程序的调用以创建产品对象。
抽象产品角色(Product):产品对象的共同父类或共同拥有的接口。
具体产品角色(Concrete Product):实现了抽象产品角色所声明的接口。工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。
工厂方法模式的优缺点:
优点:
工厂方法模式是对简单工厂模式的进一步抽象和推广,由于使用了多态,工厂方法模式保持了简单工厂模式的优点,并且克服了简单工厂模式对扩展的支持不足,由于核心类成为了抽象工厂角色,具体产品对象的产生放在了具体工厂角色中,当出现新的产品时,而不需改动核心类。
缺点:
当出现多种产品族的时候,需要新建工厂接口。
示例:
当出现新的产品(比如酸奶),就去改整个自动贩卖机,在里面添加个酸奶选项,但出现多个产品的时候,又咋办呢?
然后,我们就设定贩卖机出厂的时候不标记具体的产品,要卖具体的产品时,我们在装入产品后,贴上标签就可以了。这样专机专卖,多个产品贴个标签就可以了,省事多了。
没贴标签的贩卖机(抽象工厂角色):
/** * 抽象工厂 */ public interface Machine { public Drink factory(); }贴上标签的贩卖机(具体工厂角色):
专卖可乐的贩卖机:
/** * 自动可乐贩卖机 */ public class ColaMachine implements Machine { @Override public Drink factory() { // TODO Auto-generated method stub return new Cola(); } }专卖雪碧的贩卖机:
/** * 自动雪碧贩卖机 */ public class SpriteMachine implements Machine { @Override public Drink factory() { // TODO Auto-generated method stub return new Sprite(); } }饮料接口(抽象产品角色):
/** * 饮料 */ public interface Drink { public void taste(); }饮料产品(具体产品角色):
可乐:
/** * 可乐 */ public class Cola implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->可乐 酸甜味"); } }雪碧:
/** * 雪碧 */ public class Sprite implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->雪碧 柠檬味"); } }测试类(客户端):
public class Main { public static void main(String[] args) { Drink fruit; Machine machine; machine=new ColaMachine(); fruit=machine.factory(); fruit.taste(); machine=new SpriteMachine(); fruit=machine.factory(); fruit.taste(); } }
在该系统中,抽象工厂是核心,每当生成一个新的产品时,就需要一个新的具体工厂角色与之对应,当出现新的产品需求时,我们不需要改动抽象工厂,只需产生新的实现了抽象工厂的具体工厂类,在具体工厂类中产生新的产品对象。
使用范围:
工厂方法模式是对简单工厂模式的进一步推广,解决了它不能添加新的产品的缺点。当我们在创建单一类型的产品的时候,可以考虑时候。该模式也是抽象工厂模式在面对单一产品族的时候退化的情况。
抽象工厂模式(工具箱模式)是类的创建模式,是所有形态的工厂模式中最为抽象和最具一般性的一种形态。在上面介绍的简单工厂模式或者工厂方法模式,都是对单类产品的创建,而不能对多类产品创建,而抽象工厂模式就能很好的解决这个问题。
抽象工厂模式的一般性结构:
抽象工厂模式的类图:
抽象工厂模式的4个角色:
抽象工厂角色(Creator):担任这个角色的是抽象工厂模式的核心,任何在模式中创建对象的工厂类必须实现该接口。
具体工厂类角色(Concrete Creator):担任这个角色的时实现了抽象工厂接口的具体类,具体工厂角色含有与应用相关的逻辑,并且受到应用程序的调用以创建产品对象。
抽象产品角色(Product):产品对象的共同父类或共同拥有的接口。
具体产品角色(Concrete Product):实现了抽象产品角色所声明的接口。抽象工厂模式所创建的每一个对象都是某个具体产品角色的实例。
是对工厂方法模式的进一步抽象和扩展,可以解决多个产品族的创建问题。
以下情况考虑使用抽象工厂模式:
1.一个系统不应当依赖于产品类实例如何被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2.这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3.同属于一个产品族的产品是要在一起使用的,这一约束必须在系统的设计中体现出来。
4.系统提供一个产品类的库,所有的产品以同样的接口出现,从而客户端不再依赖于实现。
示例:
以前的贩卖机只能卖饮料,厂家市场调查发现原来卖水果也很值钱,也想卖点水果,可是贩卖机的接口只能卖饮料,那咋办?
有两个产品族,一个饮料一个水果,只实现其中一个接口都不行。那就把两个接口打包,贴上“水果”,“饮料”的按钮,然后分别按需要组合不同的水果和饮料,一个贩卖机放进去一个组合就行了。
出厂贩卖机(抽象工厂):
/** * 抽象工厂 */ public interface Machine { // 饮料 public Drink factoryDrink(); // 水果 public Fruit factoryFruit(); }里面打包水果和饮料的接口。
打上标签的贩卖机(具体工厂):
A:
/** * A族 */ public class Machine_A implements Machine { public Machine_A() { System.out.println("A 族:"); } @Override public Drink factoryDrink() { // TODO Auto-generated method stub return new Cola(); } @Override public Fruit factoryFruit() { // TODO Auto-generated method stub return new Apple(); } }该贩卖机只卖水果:苹果和饮料:可乐。
B:
/** * B族 */ public class Machine_B implements Machine { public Machine_B() { System.out.println("B 族:"); } @Override public Drink factoryDrink() { // TODO Auto-generated method stub return new Sprite(); } @Override public Fruit factoryFruit() { // TODO Auto-generated method stub return new Banana(); } }该贩卖机卖雪碧和香蕉。同样的接口,不同的产品。
水果(抽象产品):
/** * 水果 */ public interface Fruit { public void color(); }饮料(抽象产品):
/** * 饮料 */ public interface Drink { public void taste(); }苹果(具体产品,水果):
/** * 苹果 */ public class Apple implements Fruit { @Override public void color() { // TODO Auto-generated method stub System.out.println("水果-->苹果 红色"); } }香蕉(具体产品,水果):
/** * 香蕉 */ public class Banana implements Fruit { @Override public void color() { // TODO Auto-generated method stub System.out.println("水果-->香蕉 黄色"); } }可乐(具体产品,饮料):
/** * 可乐 */ public class Cola implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->可乐 酸甜味"); } }雪碧(具体产品,饮料):
/** * 雪碧 */ public class Sprite implements Drink { @Override public void taste() { // TODO Auto-generated method stub System.out.println("饮料-->雪碧 柠檬味"); } }客户端:
public class Main { public static void main(String[] args) { Fruit fruit; Drink drink; Machine machine; machine=new Machine_A(); fruit=machine.factoryFruit(); drink=machine.factoryDrink(); fruit.color(); drink.taste(); machine=new Machine_B(); fruit=machine.factoryFruit(); drink=machine.factoryDrink(); fruit.color(); drink.taste(); } }
抽象工厂模式,它是对工厂方法的进一步推广,把产品的种类扩展了,也跨越不同的产品等级按照不同的需要组合不同的产品,从而大大的扩展了使用范围。
参考:
《java与模式》