工厂模式(Factory Method)是将客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。
工厂模式适用情况:当多个子类(产品)共同继承同一父类(工厂),并由消费者的要求指定生产某一种产品时使用该种设计模式。
工厂模式分为:
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
简单工厂模式(Simple Factory)
场景:当我到麦当当吃麦辣鸡腿汉堡,你可以对服务员说:“要一个麦辣鸡翅汉堡”,服务员就会给你提供该汉堡。
分析角色:
工厂类角色(Factory):这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。 场景中的麦当当的汉堡生产线就是工厂。
抽象产品角色(Abstract Product):它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。 场景中的汉堡就是抽象产品角色。
具体产品角色(Product):工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 场景中的麦辣鸡翅汉堡就是具体产品角色。
//抽象产品角色
public interface Produce {
void doProduce();
}
//产品实例 1
public class SpicyChickenHamburg implements Produce{
public void doProduce() {
System.out.println(“offer SpicyChickenHamburg ”);
}
}
//产品实例 2 鸡腿堡
public class ChickenDrumsticksHamburg implements Produce{
public void doProduce() {
System.out.println(“do ChickenDrumsticksHamburg ”);
}
}
//工厂
public class MacDonaldHamburgFactory{
public Produce getProduct(String productName) {
if(“SpicyChickenHamburg”.equals(productName)){
return new SpicyChickenHamburg();
}else if(“ChickenDrumsticksHamburg”.equals(productName)){
return new ChickenDrumsticksHamburg ();
}else{
return null;
}
}
}
简单工厂的好处与不足:
客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品。
下面我们从开闭原则上来分析下简单工厂模式。当产品新增时,只要符合抽象产品制定,那么只要通知工厂类知道就可以提供给消费者了。那么对于产品部分来说,它是符合开闭原则的--对扩展开放、对修改关闭。
但是工厂部分每增加一样商品,就需要修改相应的商业逻辑和判断逻辑,这显然是违背开闭原则的。
在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以对于复杂的业务环境可能不太适应。
由此引出工厂方法模式。
工厂方法模式(Factory Method)
场景:当我到麦当当,由于麦当当有很多的种类的产品,当我想吃吃麦辣鸡腿汉堡时,我对服务员说:“要一个麦辣鸡翅汉堡”,同时我在想来杯大可乐,服务员会对应给我相应的汉堡和可乐。
角色分析:
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。 场景中麦当当提供产品就是抽象工厂。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。场景中汉堡和可乐是两种不同的产品,但都具有提供产品的功能,因此他们都继承与麦当当这个抽象的工厂,分别为具体工厂角色。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。 场景中汉堡和可乐都是抽象产品。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。场景中麦辣鸡翅汉堡和大可乐分别继承抽象产品中的汉堡和可乐,为具体产品角色。
//抽象产品角色
public interface Produce{
void doProduce();
}
//产品实例 1-1 麦辣鸡翅汉堡
public class SpicyChickenHamburg implements Produce{
public void doProduce() {
System.out.println(“offer SpicyChickenHamburg ”);
}
}
//产品实例 1-2 鸡腿堡
public class ChickenDrumsticksHamburg implements Produce{
public void doProduce() {
System.out.println(“do ChickenDrumsticksHamburg ”);
}
}
//产品实例 2-1 小杯可乐
public class SmallCola implements Produce{
public void doProduce() {
System.out.println(“do SmallCola ”);
}
}
//产品实例 2-2 大杯可乐
public class BigCola implements Produce{
public void doProduce() {
System.out.println(“do BigCola ”);
}
}
//抽象工厂角色
public interface MacDonaldFactory{
Produce getProduct(String productName);
}
//汉堡包工厂
public class MacDonaldHamburgFactory implements MacDonaldFactory{
public Produce getProduct( String productName) {
if(“SpicyChickenHamburg”.equals(productName)){
return new SpicyChickenHamburg();
} else if(“ChickenDrumsticksHamburg”.equals(productName)){
return new ChickenDrumsticksHamburg();
} else{
return null;
}
}
}
public class MacDonaldColaFactory implements MacDonaldFactory{
public Produce getProduct(String productName) {
if(“big”.equals(productName)){
return new BigCola ();
}else if(“small”.equals(productName)){
return new SmallCola ();
}else {
return null;
}
}
}
工厂方法使用一个抽象工厂角色作为核心来代替在简单工厂模式中使用具体类作为核心。
优点:
使用开闭原则来分析下工厂方法模式。当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。
工厂方法模式是完全符合开闭原则的!使用工厂方法模式足以应付我们可能遇到的大部分业务需求。
缺点:
当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。
抽象工厂模式(Abstract Factory)
使用场景:建议在产品种类非常多时,使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。 (例如麦当当的不同汉堡类的产品),同一产品树非类似的品种使用工厂方法(例如麦当当的汉堡和可乐类的产品族)。
对于系统中存在不同的产品树,而且产品树上存在产品族,那么这种情况下就可能可以使用抽象工厂模式了。例如(麦当当的汉堡和肯德基的汉堡不同产品树中的同类产品)
角色分析:
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
与工厂方法涉及角色如出一辙。
//抽象产品角色
public interface Product {
void doProduct ();
}
//产品实例 麦当当的大可乐
public class MBigCola implements Product {
public void doProduct ()
{
System.out.println(“do M BigCola ”);
}
}
//产品实例 麦当当的小可乐
public class MSmallCola implements Product {
public void doProduct ()
{
System.out.println(“do M SmalCola ”);
}
}
//产品实例 KFC中的大可乐
public class KFCBigCola implements Product {
public void doProduct () {
System.out.println(“do KFC BigCola ”);
}
}
//产品实例 KFC中的小可乐
public class KFCSmallCola implements Product {
public void doProduct () {
System.out.println(“do KFC SmallCola ”);
}
}
//抽象工厂角色
public interface AbstractFoctory {
Product doProduct(String productName);
}
//麦当当的可乐工厂
public class MColaFactory implements AbstractFoctory {
public Product doProduct( String productName) {
if(“Big”.equals(productName)){
return new MBigCola ();
} else if(“Small”.equals(productName)){
return new MSmallCola ();
} else{
return null;
}
}
}
//KCF的可乐生产工厂
public class KFCColaFactory implements AbstractFoctory {
public Product doProduct(String productName) {
if(“Big”.equals(productName)){
return new KFCBigCola ();
} else if(“Small”.equals(productName)){
return new KFCSmallCola ();
} else{
return null;
}
}
}