美文网首页
设计模式--工厂模式

设计模式--工厂模式

作者: Qi0907 | 来源:发表于2018-07-09 11:22 被阅读0次

    一、简单工厂
    举个栗子:
    开个披萨店:

    Pizza orderPizza() {
        Pizza pizza = new Pizza(); //创建个pizza
        pizza.prepare(); //备料
        pizza.bake(); //烘烤
        pizza.cut(); //切片
        pizza.box(); //装盒
    }
    

    披萨店不能只有一种披萨,要做各种类型的披萨怎么办呢?

    Pizza orderPizza(String type) {//要做什么pizza就传入pizza的种类
        Pizza pizza;
    if (type.equals(“cheese”)) { //根据pizza的类型,来实例化正确的具体类
            pizza = new CheesePizza();
    } else if ...
        
        pizza.prepare(); //备料
        pizza.bake(); //烘烤
        pizza.cut(); //切片
        pizza.box(); //装盒
    }
    

    披萨店扩张了,制作的披萨种类更多了,有些披萨卖得不好,不做了,这怎么做呢?
    只能在上面代码里删掉一些if else,再添加上一些if else。在上面这段代码中,if else这段会随着需求的变化而变化,但对披萨的备料,烘烤等操作是不会变化的。

    Tips:
    开闭原则:
    扩展开放,对修改关闭。一个软件实体应该通过扩展来实现变化,而不是通过修改已有代码来实现变化。

    很明显,上面的这种设计,违背了开闭原则,这就到了使用封装的时候了。把会经常修改的if else这段代码抽离到另一个对象中,这个对象只负责创建披萨。
    这个新对象SimplePizzaFactory就称为“工厂”,专门用来生产不同种类的披萨,orderPizza()就是这个对象的客户,当需要披萨时,就叫披萨工厂做一个,至于怎么做,就不用关心了。
    卖披萨分三步:
    1.建个披萨工厂专门做披萨

    public class SimplePizzaFactory { //只负责创建披萨
        public Pizza createPizza(String type) { //这个方法为所有用户实例化新对象
            Pizza pizza = null;
    
            if (type.equals(“cheese”)) { //之前的if else
                pizza = new CheesePizza();
            } else if ...
    
            return pizza;
         }
    }
    

    2.建个披萨店

    public class PizzaStore {
        SimplePizzaFactory factory; //为披萨店PizzaStore加上对SimplePizzaFactory的引用
        public PizzaStore (SimplePizzaFactory factory) { //披萨店PizzaStore的构造器,以一个工厂做参数
            This.factory = factory;
        }
        public Pizza orderPizza (String type) {
            Pizza pizza;
            pizza = factory.createPizza(type);//通过传入类型来使用工厂加工披萨
            pizza.prepare(); //备料
            pizza.bake(); //烘烤
            ...
            return pizza;
        }
    }
    

    3.披萨卖起来了

    pubic class PizzaTest {
        public static void main (String[] args) {
            SimplePizzaFactory factory = new SimplePizzaFactory();//创建一个披萨工厂
            PizzaStore story = new PizzaStore(factory); //建立一个披萨店,从披萨工厂里获取披萨
            store.orderPizza(“Cheese”);//选择披萨的具体口味
        }
    }
    

    简单工厂其实不是一个设计模式,反而比较像一种编程习惯,把变化的部分单独封装起来。

    二、工厂模式
    披萨店有了加盟店啦~~但是每个加盟店想提供适合自己所在区域口味的披萨,所以加盟店需要有一个适合自己的工厂。
    还是卖披萨的那三步:
    1.建一个专门生产纽约风味的披萨工厂

    abstract class PizzaFactory { 
        public abstract Pizza createPizza();
    }
    
    public class NYPizzaFactory extent PizzaFactory {//继承抽象工厂类,创建具体的实例方法
        public Pizza createPizza(String type) { 
            ... //个性化定制纽约口味披萨
            return pizza;
        }
    }
    

    2.开个加盟店
    到这里发现,加盟店也需要个性化定制啊,不能通用就是PizzaStore,也得有什么NYPizzaStore啊,那就把披萨店也抽象出来。

    public abstract class PizzaStore { //创建一个抽象的披萨店PizzaStore类
        public Pizza orderPizza(String type) {//处理披萨订单
            Pizza pizza;
            pizza = createPizza(type);//调用的就是下方的createPizza方法,这个方法由各个加盟店自己定义,也就是说每个PizzaStore的子类都会覆盖createPizza()方法
    
            //pizza的后续制作不变,加盟店无法影响他们,加盟店只负责确定口味,在外部调用orderPizza,而orderPizza里的createPizza是加盟店自己定义的具体制作什么口味的披萨
            pizza.prepare(); //备料
            pizza.bake(); //烘烤
            ...
            return pizza;
        }
        protected abstract Pizza createPizza(String type);//由各个加盟店自己决定如何做披萨
    }
    

    现在就开个加盟店

    public class NYPizzaStore extends PizzaStore {
        Pizza createPizza(String item) { //必须实现createPizza()方法,因为在PizzaStore里他是抽象的
            if (item.equals(“cheese”)) { //具体的披萨口味
                return new NYStyleCheesePizza();
            } else if ...
        }
    }
    

    3.卖个纽约风味的芝士披萨

    public class PizzaTest {
        public Static void main(String[] args) {
            PizzaStroe nyStore = new NYPizzaStore();//建个纽约加盟店
            Pizza pizza = nyStore.orderPizza(“cheese”);//定个cheese披萨
        }
    }
    

    Tips:
    重点解释abstract Pizza createPizza(String type);


    image.png

    工厂模式用来封装对象的常见,通过让子类决定应该创建的对象,达到将对象创建的过程封装起来的目的。
    工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
    工厂模式类图:


    image.png
    三、抽象工厂模式
    抽象工厂模式提供一个接口,用于创建相关或依赖对象的“家族”(敲黑板,重点),而不需要明确指定具体类。
    抽象工厂的任务是定义一个负责创建一组产品的接口,这个接口内的每个方法都负责创建一个具体产品,同时利用实现抽象工厂的子类来提供这些具体的做法。

    工厂方法用的是继承,而抽象工厂是通过对象的组合来实现。
    再通过披萨店的例子,来看看抽象工厂模式。
    还是卖披萨的那三步:
    1.建立工厂
    A.建一个专门生产纽约风味的披萨工厂

    abstract class PizzaFactory { 
        public abstract Pizza createPizza();
    }
    
    public class NYPizzaFactory extent PizzaFactory {//继承抽象工厂类,创建具体的实例方法
        public Pizza createPizza(String type) { 
            ... //个性化定制纽约口味披萨
            return pizza;
        }
    }
    

    B.制作披萨所用的原料需要保证质量,就需要建立一家生产原料的工厂,这样每家加盟店都从这个原料工厂里进货,确保质量。但是各个加盟店所产披萨的口味不同,所需原料也有细微差别(纽约的芝士和芝加哥的芝士,口味上是不一样的),与建立披萨工厂的思想一样,还是先建立一个原料生产工厂,然后每个区域继承这个工厂,来生产自己各自口味的原料。
    定义原料工厂接口,它负责创建所有的原料:

    public interface PizzaIngredientFactory{
        public Dough createDough(); //生产面团
        public Sauce createSauce(); //生产酱料
        ...
    }
    

    那么纽约原料工厂生产的原料就是纽约口味的啦

    public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
        public Dough createDough() {
            return new ThinCrustDough();
        }
        public Sauce createSauce() {
            return new MarinaraSauce();
        }
        ...
    }
    

    需要使用原料工厂生产出的原料来制作披萨

    public abstract class Pizza {
        Dough dough;
        Sauce sauce;
        ...//制作披萨所需的各种原料
    
        abstract void prepare();//把prepare()方法声明成抽象,由不同地区的原料工厂提供原料
    
        //之前的烘烤、切片等工序不变
        void back() {
        }
        void cut() {
        }
        ...
    }
    

    之后我们就可以使用原料工厂生产的原料来制作披萨啦,原料的质量得到了保证。
    制作一个芝士披萨

    public class CheesePizza extends Pizza {
        PizzaIngredientFactory ingredientFactory;
        public CheesePizza (pizzaIngredientFactory ingredientFactory) {
            this.ingredientFactory = ingredientFactory;
        }
    
        void prepare() {//从原料工厂里获取原料制作披萨
            dough = ingredientFactory.createDough();
            Sauce = ingredientFactory.createSauce();
            ...
        }
    }
    

    Tips:


    image.png

    2.开个加盟店

    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);
            } else if ...
            return pizza;
        }
    }
    

    3.卖个纽约风味的芝士披萨

    public class PizzaTest {
        public Static void main(String[] args) {
            PizzaStroe nyStore = new NYPizzaStore();//建个纽约加盟店
            Pizza pizza = nyStore.orderPizza(“cheese”);//定个cheese披萨
        }
    }
    

    看看抽象工厂的类图


    image.png

    结合披萨店再来看


    image.png
    结合上面的类图再回顾下抽象工厂的定义,抽象工厂的任务是定义一个负责创建“一组”产品的接口,通过对象的“组合”来实现。
    在披萨店的例子中,创建了三个接口:披萨,披萨店,披萨原料工厂,通过组合这三个接口,实现了对各个加盟店的控制:保证披萨的制作工艺,和原料供应

    相关文章

      网友评论

          本文标题:设计模式--工厂模式

          本文链接:https://www.haomeiwen.com/subject/xbuzuftx.html