简单工厂与工厂模式原理及案例分析

  工厂方法的规范性定义描述为:工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

  在学习工厂方法前,我们应该先了解简单工厂这一种伪模式。之所以称之为伪模式,是因为严格意义上讲这并不算是一种模式,个人感觉更像是将某一功能抽象成了一个功能函数。

  编程的场景为:有一个专门生产果冻的生产商,可以生产出苹果、香蕉、橘子三种口味的果冻。如果现在该生产商被要求生产苹果口味的果冻,用简单工厂伪模式是如何编码的呢?

  首先,我们需要有果冻父类,并且根据不同口味的果冻定义出各种果冻的具体子类。这一层我称之为产品层:

 父类Jelly表现为:

public abstract class Jelly {

    String name;             //果冻名称
    String fruitMaterial;   //果冻的材料
    String pigment;          //染色

    public void prepare(){
        System.out.println("The jelly's name is "+name);
        System.out.println("The jelly's fruitMaterial is "+fruitMaterial);
        System.out.println("The jelly's pigment is "+pigment);
    }

    public void melt(){
        System.out.println("melt the material");
    }
    public void put(){
        System.out.println("put the fruit");
    }
    public void cold(){
        System.out.println("cold the material");
    }
    public void box(){
        System.out.println("put the jelly into boxes");
    }

    public String getName() {
        return name;
    }
}

 以下是三种口味果冻的子类:

 

public class AppleJetty extends Jelly{

    public AppleJetty() {
        this.name = "appleJetty";
        this.fruitMaterial = "apple";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the apple");
    }
}


public class BananaJetty extends Jelly{

    public BananaJetty() {
        this.name = "bananaJetty";
        this.fruitMaterial = "banana";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the banana");
    }
}


public class OrangeJetty extends Jelly{

    public OrangeJetty() {
        this.name = "orangeJetty";
        this.fruitMaterial = "orange";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the orange");
    }
}

 产品层到此为止,接下来就需要工厂层来生产产品。这里用JellyCompany类来表示

public class JellyCompany {

    SimpleJettyFactory simpleJettyFactory;

    public JellyCompany(SimpleJettyFactory simpleJettyFactory) {
        this.simpleJettyFactory = simpleJettyFactory;
    }

    public Jelly orderJelly(String type){
        Jelly jelly;
        jelly = simpleJettyFactory.createJetty(type);

        jelly.prepare();
        jelly.melt();
        jelly.put();
        jelly.cold();
        jelly.box();

        return jelly;
    }
}

 

 此时JellyCompany类里面的SimpleJettyFactory就是像抽象出来的功能函数。它的具体实现为: 

public class SimpleJettyFactory {
    public Jelly createJetty(String type){
        Jelly jelly = null;

        if(type.equals("appleJetty")){
            jelly = new AppleJetty();
        }else if(type.equals("orangeJetty")){
            jelly = new OrangeJetty();
        }else if(type.equals("bananaJetty")){
            jelly = new BananaJetty();
        }

        return jelly;
    }
}
   最后就是运行类SimpleFactorySimulator:
public class SimpleFactorySimulator {
    public static void main(String[] args){

        SimpleJettyFactory simpleJettyFactory = new SimpleJettyFactory();
        JellyCompany jellyCompany = new JellyCompany(simpleJettyFactory);
        Jelly jelly = jellyCompany.orderJelly("appleJetty");
        System.out.println("该公司已生产 "+jelly.getName());
    }
}
   输出结果为:
The jelly's name is appleJetty
The jelly's fruitMaterial is apple
The jelly's pigment is no
melt the material
put the apple
cold the material
put the jelly into boxes
该公司已生产 appleJetty
   但是与上面只是抽出功能函数的简单工厂比较,工厂模式则更适于变化。现在如果该公司成立了一个分公司:上海分公司(这里默认该公司的总部在北京)。但是由于地域性饮食差异,这使得两个不同地方的公司生产的果冻流程有一些差异:北京总公司生产的果冻,其中的果肉倾向于更多更大,而上海分公司的果冻则更倾向于多放糖。如果某客户要求生产北京的苹果果冻和上海的橘子果冻,那么简单工厂很明显已经不适应这种多变化需要。这时候我们来研究一下工厂模式:  同样的,先列出model层,果冻父类Jelly为:
public abstract class Jelly {

    String name;
    String fruitMaterial;
    String pigment;

    public void prepare(){
        System.out.println("The jelly's name is "+name);
        System.out.println("The jelly's fruitMaterial is "+fruitMaterial);
        System.out.println("The jelly's pigment is "+pigment);
    }

    public void melt(){
        System.out.println("melt the material");
    }
    public void put(){
        System.out.println("put the fruit");
    }
    public void cold(){
        System.out.println("cold the material");
    }
    public void box(){
        System.out.println("put the jelly into boxes");
    }

    public String getName() {
        return name;
    }

}
   下面依次是上海分公司所能生产的三种果冻:
public class ShanghaiAppleJelly extends Jelly{

    public ShanghaiAppleJelly() {
        this.name = "ShanghaiAppleJetty";
        this.fruitMaterial = "apple";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the apple and lots of sugar");
    }
}


public class ShanghaiBananaJelly extends Jelly{

    public ShanghaiBananaJelly() {
        this.name = "ShanghaiBananaJetty";
        this.fruitMaterial = "banana";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the banana and lots of sugar");
    }
}


public class ShanghaiOrangeJelly extends Jelly{

    public ShanghaiOrangeJelly() {
        this.name = "ShanghaiOrangeJetty";
        this.fruitMaterial = "orange";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the orange and lots of sugar");
    }
}
   北京总公司所能生产的三种果冻:
public class BeijingAppleJelly extends Jelly {

    public BeijingAppleJelly() {
        this.name = "BeijingAppleJelly";
        this.fruitMaterial = "apple";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the apple and cut into large pieces");
    }
}


public class BeijingBananaJelly extends Jelly{

    public BeijingBananaJelly() {
        this.name = "BeijingBananaJetty";
        this.fruitMaterial = "banana";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the banana and cut into large pieces");
    }
}


public class BeijingOrangeJelly extends Jelly{

    public BeijingOrangeJelly() {
        this.name = "BeijingOrangeJetty";
        this.fruitMaterial = "orange";
        this.pigment = "no";
    }

    @Override
    public void put(){
        System.out.println("put the orange and cut into large pieces");
    }
}
   下面是工厂层:抽象父类JellyCompany
public abstract class JellyCompany {

    public Jelly orderJelly(String type){
        Jelly jelly;
        jelly = createJelly(type);   //注意此处将实例化延迟到了实现子类

        jelly.prepare();
        jelly.melt();
        jelly.put();
        jelly.cold();
        jelly.box();

        return jelly;
    }

    abstract Jelly createJelly(String type);
}
   北京总公司实现子类与上海子公司实现子类
public class BeijingJellyCompany extends JellyCompany {

    Jelly createJelly(String type){
        if(type.equals("appleJelly")){
            return new BeijingAppleJelly();   //因为是北京公司,所以采用生产北京果冻的生成方法
        }else if(type.equals("orangeJelly")){
            return new BeijingOrangeJelly();
        }else if(type.equals("bananaJelly")){
            return new BeijingBananaJelly();
        }else
            return null;
    }
}

public class ShanghaiJellyCompany extends JellyCompany {

    Jelly createJelly(String type){
        if(type.equals("appleJelly")){
            return new ShanghaiAppleJelly();
        }else if(type.equals("orangeJelly")){
            return new ShanghaiOrangeJelly();
        }else if(type.equals("bananaJelly")){
            return new ShanghaiBananaJelly();
        }else
            return null;
    }
}
   最后是运行类JellySimulator:
public class JellySimulator {

    public static void main(String[] agrs){
        JellyCompany beijingJellyComyany = new BeijingJellyCompany();
        JellyCompany shanghaiJellyComyany = new ShanghaiJellyCompany();

        Jelly jelly = beijingJellyComyany.orderJelly("appleJelly");
        System.out.println("BeijingJelly : "+jelly.getName());

        System.out.println("==================");

        jelly = shanghaiJellyComyany.orderJelly("orangeJelly");
        System.out.println("ShanghaiJelly : "+jelly.getName());
    }
}
   运行结果为:
The jelly's name is BeijingAppleJelly
The jelly's fruitMaterial is apple
The jelly's pigment is no
melt the material
put the apple and cut into large pieces
cold the material
put the jelly into boxes
BeijingJelly : BeijingAppleJelly
==================
The jelly's name is ShanghaiOrangeJetty
The jelly's fruitMaterial is orange
The jelly's pigment is no
melt the material
put the orange and lots of sugar
cold the material
put the jelly into boxes
ShanghaiJelly : ShanghaiOrangeJetty
   通过上面的两个例子大家可以比较一下简单工厂与工厂模式的区别: 简单工厂更像是抽象出一个功能函数,而工厂模式则是抽象父类定义好一系列完整流程,而具体生产什么样产品的实例化交给子类去做。就变化的适应性而言,工厂模式更为优秀。  

  

猜你喜欢

转载自chn-wangzhenjiang.iteye.com/blog/2317565