工厂模式

工厂模式在《Java与模式》中分为三类:
1)简单工厂模式(Simple Factory):不利于产生系列产品;
2)工厂方法模式(Factory Method):又称为多形性工厂;
3)抽象工厂模式(Abstract Factory):又称为工具箱,产生产品族,但不利于产生新的产品;
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

简单工厂模式案例:

又称静态工厂方法(Static Factory Method)模式。它存在的目的很简单:定义一个用于创建对象的接口。

定义:简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

 

该模式中包含的角色及其职责: 

工厂(Creator)角色
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(Product)角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

没有抽象工厂角色,产品由一个工厂来制造 

优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;写代码的人都知道代码要模块化,一个函数含有的代码最好不要太多
这些缺点在工厂方法模式中得到了一定的克服。
使用场景
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

//简单工厂模式 
public  interface  Fruit {
     // 生长 
       void  grow();
      // 收获 
       void  harvest();
      // 种植 
       void  plant();
} 
 
 public   class  Apple  implements  Fruit { // 通过implements实现接口Fruit 
      private   int  treeAge;
    
     public   void  grow() {
        log( " Apple is growing " );
    } 
    
     public   void  harvest() {
        log( " Apple has been harvested " );
    } 
    
     public   void  plant() {
        log( " Apple ha been planted " );
    } 
    
     public   static   void  log(String msg) {
        System.out.println(msg);
    } 
    
     public   int  getTreeAge() {
         return  treeAge;
    } 
    
     public   void  setTreeAge( int  treeAge) {
         this .treeAge = treeAge;
    } 
} 

public class Grape implements Fruit{
    private boolean seedless;
    public void grow(){
        log("Grape is growing.");
    }
    
    public void harvest(){
        log("Grape has been harvested");
    }
    
    public void plant(){
        log("Grape ha been planted");
    }
    
    public static void log(String msg){
        System.out.println(msg);
    }

    public boolean isSeedless() {
        return seedless;
    }

    public void setSeedless(boolean seedless) {
        this.seedless = seedless;
    }
}

public class Strawberry implements Fruit{
    public void grow(){
        log("Strawberry is growing");
    }
    
    public void harvest(){
        log("Strawberry has been harvested");
    }
    
    public void plant(){
        log("Strawberry has been planted");
    }
    
    public static void log(String msg){
        System.out.println(msg);
    }
}


public class FruitGardener{
    public static Fruit factory(String which)throws Exception{
        if(which.equalsIgnoreCase("apple")){
            return new Apple();
        }else if(which.equalsIgnoreCase("strawberry")){
            return new Strawberry();
        }else if (which.equalsIgnoreCase("grape")){
            return new Grape();
        }else{
            throw new Exception("Bad fruit request");
        }
    }
}

public class People {
    public static void main(String[] args) throws Exception {
        FruitGardener fg=new FruitGardener();
        Fruit ap=fg.factory("Apple");
        ap.grow();
        Fruit gp=fg.factory("Grape");
        gp.plant();
        
        Fruit dd=fg.factory("ddd");//抛出Bad fruit request异常
    }
}

 

-----------------------------------

工厂方法模式

工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。
  来看下它的组成: 抽象工厂角色 具体工厂角色 抽象产品角色 具体产品角色
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;
而且这样使得结构变得灵活起来——当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,
那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的!

优点:容易扩展,增加新的产品比较方便,不需要修改原有的代码,直接添加新的代码即可。

//抽象产品角色
public interface Moveable {
    void run();
}
//具体产品角色
public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.println("plane....");
    }
}

public class Broom implements Moveable {
    @Override
    public void run() {
        System.out.println("broom.....");
    }
}

//抽象工厂
public abstract class VehicleFactory {
    abstract Moveable create();
}
//具体工厂
public class PlaneFactory extends VehicleFactory{
    public Moveable create() {
        return new Plane();
    }
}
public class BroomFactory extends VehicleFactory{
    public Moveable create() {
        return new Broom();
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        VehicleFactory factory = new BroomFactory();
        Moveable m = factory.create();
        m.run();
    }
}

 抽象工厂模式:

优缺点
优点
分离接口和实现,客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。
使切换产品族变得容易,因为一个具体的工厂实现代表的是一个产品族。
缺点
不太容易扩展新的产品,如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。

适用场景:

多个系列的产品,每个系列又包含多种产品。是一种大众化的用法,应用的场景比较复杂。

//两种抽象产品:水果、蔬菜//在我看来,这两货还可以写个父类
public interface Fruit{
}

public interface Veggie{
}

//四种具体产品:北方水果,热带水果,北方蔬菜,热带蔬菜
//Northern Fruit
public class NorthernFruit implements Fruit{
}

//TropicalFruit
public class TropicalFruit implements Fruit{
}

//NorthernVeggie
public class NorthernVeggie implements Veggie{
}

//TropicalVeggie
public class TropicalVeggie implements Veggie{
}
--------------------------------------
//抽象工厂角色
public interface Gardener{
   public Fruit createFruit(String name);
   public Veggie createVeggie(String name);
}

//具体工厂角色:北方工厂,热带角色
public class NorthernGardener implements Gardener{
    public Fruit createFruit(String name){
        return new NorthernFruit(name);
    }
    
    public Veggie createVeggie(String name){
        return new NorthernVeggie(name);
    }
}

public class TropicalGardener implements Gardener{
    public Fruit createFruit(String name){
        return new TropicalFruit(name);
    }
    
    public Veggie createVeggie(String name){
        return new TropicalVeggie(name);
    }
}

 

posted @ 2015-03-20 20:23  牧 天  阅读(176)  评论(0)    收藏  举报