作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

  • 变量不可以持有具体类的引用(如果使用new就会持有具体类的引用,可以使用工厂模式来避免)。
  • 不要让类派生自具体类(都是从抽象类或接口派生出来的)。
  • 不要覆盖基类中已经实现的方法。(这样会导致继承的复杂度上升,同时说明基类不合适被继承——基类中已实现的方法该由子类共享)
  •  

    5.抽象工厂模式:

    我们现在的场景是要在Pizza上采用不同的原料,针对不同的分店,首先我们先定义一个产生原料的工厂(抽象工厂类),我们有六种原料要供应:

     

    public interface PizzaIngredientFactory {//抽象工厂的任务是定义一个负责创建一组产品的接口,在这个接口中的每个方法都负责创建一个具体的产品,利用抽象工厂的子类提供具体做法。
       
    public Dough createDough();
        public Sauce createSauce();
        public Cheese createCheese();
        public Veggies[] createVeggies();
        public Pepperoni createPepperoni();
        public Clams createClam();
    }

     

    (注:如果每个具体工厂类内部需要实现某种通用机制,这里就采用抽象类)

     

    我们根据这一模式构建各地的分工厂(具体工厂类):

    public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
        public Dough createDough() { {//
    采用工厂方法创建具体的产品
            return new ThinCrustDough();
        }
        public Sauce createSauce() {
            return new MarinaraSauce();
        }
        public Cheese createCheese() {
            return new ReggianoCheese();
        }
       public Veggies[] createVeggies()  
            Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
            return veggies;
        }
        public Pepperoni createPepperoni() {
            return new SlicedPepperoni();
        }

        public Clams createClam() {
            return new FreshClams();
        }
    }

    现在我们就做一个pizza,使用原料工厂提供的原料,这是一个抽象产品类:

    public abstract class Pizza {
        String name;

        Dough dough;
        Sauce sauce;
        Veggies veggies[];
        Cheese cheese;
        Pepperoni pepperoni;
        Clams clam;

        abstract void prepare(); //这个方法是要具体产品类实现,表示使用一族产品(这里指佐料)。

        void bake() {
            System.out.println("Bake for 25 minutes at 350");
        }

        void cut() {
            System.out.println("Cutting the pizza into diagonal slices");
        }

        void box() {
            System.out.println("Place pizza in official PizzaStore box");
        }

        void setName(String name) {
            this.name = name;
        }

        String getName() {
            return name;
        }

        public String toString() {
                }
    }

    针对这一个基本的方式,我们构建具体的Pizza(这是具体产品类):

    public class CheesePizza extends Pizza {
      
    PizzaIngredientFactory ingredientFactory;
        public CheesePizza(PizzaIngredientFactory ingredientFactory) {
            this.ingredientFactory = ingredientFactory;
        }
        void prepare() {
            System.out.println("Preparing " + name);
           
    dough = ingredientFactory.createDough();
            sauce = ingredientFactory.createSauce();
            cheese = ingredientFactory.createCheese();
        }
    }

     

    接着,我们要在店面上进行抽象(抽象工厂类):

     

    public abstract class PizzaStore {
        protected abstract Pizza createPizza(String item);
        public Pizza orderPizza(String type) {
            Pizza pizza = createPizza(type); 
            System.out.println("--- Making a " + pizza.getName() + " ---");
            pizza.prepare(); 
            pizza.bake();
            pizza.cut();
            pizza.box();
            return pizza;
        }
    }

     

    在这个抽象的基础上我们开一家分店(具体工厂类):

    public class NYPizzaStore extends PizzaStore {
        protected Pizza createPizza(String item) {
            Pizza pizza = null;
            PizzaIngredientFactory ingredientFactory =
                new NYPizzaIngredientFactory();
            if (item.equals("cheese")) {
                pizza = new CheesePizza(ingredientFactory);
                pizza.setName("New York Style Cheese Pizza");
            } else if (item.equals("veggie")) {
                pizza = new VeggiePizza(ingredientFactory);
                pizza.setName("New York Style Veggie Pizza");
            } else if (item.equals("clam")) {
                pizza = new ClamPizza(ingredientFactory);
                pizza.setName("New York Style Clam Pizza");
            } else if (item.equals("pepperoni")) {

                pizza = new PepperoniPizza(ingredientFactory);
                pizza.setName("New York Style Pepperoni Pizza");
            }
            return pizza;
        }
    }

    现在我们试着订购一个Pizza:

    public class PizzaTestDrive {
        public static void main(String[] args) {
            PizzaStore nyStore = new NYPizzaStore();
            Pizza pizza =
    nyStore.orderPizza("cheese");
            System.out.println("Ethan ordered a " + pizza + "/n");
            }
    }

    抽象工厂方法提供了一个接口(此例中为PizzaIngredientFactory),用于创建相关或者依赖的对象家族,而不需要明确指定具体类,每个家族成员(此例为NYPizzaIngredientFactory)都负责创建一个具体的产品。与工厂方法的区别在于:工厂方法使用继承,针对的是类,利用工厂方法创建对象要扩展一个类,并覆盖它的工厂方法(例如这里的createPizza)——用来创建对象,工厂方法的实质在于通过子类创建对象;抽象工厂方法使用的是组合(ingredientFactory),针对的是一族对象,要使用这个工厂要首先将其实例化,然后将它传入一些针对抽象类型所写的代码中,优点在于可以把一群相关的产品集合起来,具体的工厂都是由工厂方法(prepare)创建的(这就是工厂方法和抽象工厂方法的联系)。在这个例子中商店的实现是采用的工厂方法,而制作Pizza的原料相关的类是采用的抽象工厂方法。

     

    总结起来,这三者如下:

    ==========================

     

    简单工厂方法中,

    首先包括一个“抽象产品类”(该类可以是接口Interface,也可以是实际的类Class,本例中是Pizza),所有需要的产品类都是该“抽象产品类”的子类(如果是接口的话,那么就是说所有产品类都继承了该接口),本例中为各种XXPizza。

     

    另外还包含一个具体的工厂类(本例为SimplePizzaFactory),所有需要的产品类都是该类生成的产品类对象。生成产品类的方法,其内部一般是类似于switch的结构,根据输入的标志,选择创建不同类型的对象。由于不知道创建的对象到底是哪个类的,所以方法的返回值的类型是“抽象产品类”。譬如,Pizza createPizza(String type),type就是一个标志,返回的是Pizza这个抽象产品类。

     

    ==========================

     

    工厂方法中,

    首先包括一个抽象产品类(本例中是Pizza),可以派生出多个具体产品类(本例为XXXPizza),这个和简单工厂方法没有区别。 

     

    另外还包含一个抽象工厂类(本例为PizzaStore),可以派生出具体工厂类(本例为XXXPizzaStore,这个与简单工厂方法中的具体工厂类没有区别), 每个具体工厂类(比如本例的ChicagoPizzaStore )可以根据输入标志创建一个具体产品类的实例。

     

    较之简单工厂方法,工厂方法对于工厂类进行了抽象产生了一个抽象工厂类,通过这个抽象工厂类规定了一系列流程框架(orderPizza方法),另外,还将具体产品类的创建交给了具体的工厂类(createPizza在XXXPizza类中的实现)——也就是说,有多个具体工厂类相对应多个具体产品类,工厂类和产品类的耦合度下降。在本例中,如果不使用工厂方法,那么createPizza除了传入Pizza的类型还要传入商店的地点信息,譬如Chicago,这样的耦合度就会很大。

     

    ==========================

     

    抽象工厂方法中,

     

    首先,包括一个抽个产品类(本例中为Pizza),该抽象产品类可以派生出多个具体产品类(本例为XXXPizza),在每个具体产品类中以组合的形式将另一个抽象工厂类(本例为PizzaIngredientFactory )的引用包含进来,完成一群具体产品类的构建(XXXPizza的Prepare方法)。

     

    另外还包含两个抽象工厂类,本例中PizzaStore,可以派生出多个具体工厂类XXXPizzaStore,这个与简单工厂方法中的具体工厂类没有区别,  每个具体工厂类可以创建一个具体产品类的实例(XXXPizza),但是这个具体产品类的实例比较特殊,是利用另一个抽象工厂类PizzaIngredientFactory 的具体工厂类创建的一群具体产品类而构建(XXXPizza的Prepare方法),请注意这个类才是抽象工厂方法的实质。

     

    在线视频:http://v.youku.com/v_show/id_XMjU1NTkyNDU2.html

     

    参考文献:http://www.cnblogs.com/lengjunming/archive/2011/01/13/1934830.html

     

    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/

    相关文章:

    • 2021-09-16
    • 2021-11-08
    • 2021-12-23
    • 2021-11-05
    • 2021-09-12
    • 2021-12-13
    • 2021-08-30
    • 2021-08-08
    猜你喜欢
    • 2022-12-23
    • 2021-05-23
    • 2021-10-09
    • 2022-01-09
    • 2021-07-21
    • 2022-12-23
    • 2022-12-23
    相关资源
    相似解决方案