首页 > 其他分享 >工厂模式

工厂模式

时间:2022-12-14 21:23:54浏览次数:40  
标签:披萨 模式 工厂 new Pizza type public pizza

想多了都是问题,想通了都是答案

第一部分,简单工厂模式

哪朵玫瑰没有荆棘,最好的报复是美丽,最美的盛开是反击,别让谁去改变了你。

当看到new,就会想到具体

先看一段代码

Duck duck;

if (picnic) {
duck = new MallardDuck();
} else if (hunting) {
duck = new DecoyDuck();
} else if (inBathTub) {
duck = new RubberDuck();
}

究竟要实例化哪个类,要在运行时由一些条件来决定。当看到这样的代码,一旦有变化或扩展,就必须重新打开这段代码进行检查和修改,维护与更新困难,也更容易犯错。

识别变化的方面

你有一家披萨店,你的代码可能这么写:

Pizza orderPizza() {
   Pizza pizza = new Pizza();

   pizza.prepare();
   pizza.bake();
   pizza.cut();
   pizza.box();
   return pizza;
}

现在,你需要更多的披萨类型:

Pizza orderPizza(String type) {
   Pizza pizza;

   // 根据不同的类型,创建不同的披萨
   if (type.equals("cheese")) {
   pizza = new CheesePizza();
  } else if (type.equals("greek")) {
   pizza = new GreekPizza();
  } else if (type.equals("pepperoni")) {
   pizza = new PepperoniPizza();
  }

   pizza.prepare();
   pizza.bake();
   pizza.cut();
   pizza.box();
   return pizza;
}

但是现在其它的披萨店推出了更多口味更加流行的披萨口味,你为了不被淘汰,也要更新店铺的披萨口味同时把其中不受欢迎的披萨进行淘汰。很明显,上面中间那段代码就要根据情况不停地进行修改,违反了代码的设计原则,对扩展开发,对修改关闭。

封装创建对象的代码

根据代码的设计原则,把其中易于改变的地方提出来单独进行封装。

Pizza orderPizza(String type) {
   Pizza pizza;

   // 这易于变化的部分,提处理单独封装

   pizza.prepare();
   pizza.bake();
   pizza.cut();
   pizza.box();
   return pizza;
}

建立一个简单工厂

public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;

       // 根据不同的类型,创建不同的披萨
       if (type.equals("cheese")) {
       pizza = new CheesePizza();
      } else if (type.equals("greek")) {
       pizza = new GreekPizza();
      } else if (type.equals("pepperoni")) {
       pizza = new PepperoniPizza();
      }
       retirn pizza;
}
}

把这个提出来处理的对象称为“工厂”,现在orderPizza()就成了这个简单工厂的客户,当需要生产披萨时,就叫工厂生产一个。

这么做有什么好处?似乎只是把问题搬到了另一个对象罢了,问题依然存在。

不,最直观的一个方面就是SimplePizzaFactory可以不单单为orderPizza服务了,他可以有许多个客户。比如

有一个外卖服务类HmoeDelivery,会对工厂生成的披萨进行不同的处理,即修改下面这段代码

 pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();

换成其他的处理方式。所以,把创建披萨的代码包装起来,当以后实现改变时,只需要修改这个类即可,其它的客户类不用动。

重做pizzaStore类,定义简单工厂

public class PizzaStore {
SimplePizzaFactory factory;

public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}

Pizza orderPizza(String type) {
       Pizza pizza;

pizza = factory.createPizza(type);
       pizza.prepare();
       pizza.bake();
       pizza.cut();
       pizza.box();
       return pizza;
  }
}

要知道,其实上面这种设计模式,并不是传统意义上的工厂模式,而是一种好的编程习惯。

第二部分,工厂方法模式

加盟披萨店

现在你的披萨店经营有成,击败了其它的竞争者,大家都希望披萨店能够在自家门口有加盟店。

但是,由于地域之间的差别,每一家加盟店都可能要提供不同风味的披萨(比如纽约、芝加哥、加州)。

第一个做法,就是创建几个不同的工厂

NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("Veggie");

根据上面的方法,各个区域的加盟店确实使用的是你的工厂生产的披萨饼。但是,对于披萨的制作流程确实没有按照总公司的制作流程

 pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();

这些加盟店不按照规定的流程走,使得做出来的披萨非常难吃,这大大影响了披萨店的口碑。所以,你想要有一套框架,在各个区域加盟店能生产符合地域口味的披萨,同时又能严格按照总公司的披萨制作流程,保证披萨的质量。

给披萨店制定框架

既能根据地域生产不同口味披萨,同时严格执行披萨制作流程

定义总公司披萨店抽象类,其它店铺继承这个类

public abstract class PizzaStore {
Pizza orderPizza(String type) {
       Pizza pizza;

pizza = createPizza(type);

       pizza.prepare();
       pizza.bake();
       pizza.cut();
       pizza.box();
       return pizza;
  }
   
   // 把制作不同口味的披萨放到子类加盟店中做决定
   abstract Pizza createPizza(String type)
}

开一家纽约披萨加盟店

public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;

       // 根据不同的类型,创建不同的披萨
       if (type.equals("cheese")) {
       pizza = new CheesePizza();
      } else if (type.equals("greek")) {
       pizza = new GreekPizza();
      } else if (type.equals("pepperoni")) {
       pizza = new PepperoniPizza();
      }
       return pizza;
}
}

工厂方法用来处理对象的创建,并将这样的行为封装在子类中,实际生产什么口味的披萨由子类来决定。

public static void main(String[] args) {
NYPizzaStore nyStore = new NYPizzaStore();
ChicagoPizzaStore chicagoStore = new ChicagoPizzaStore();

Pizza pizza = nyStore.orderPizza("cheese");
Pizza pizza = chicagoStore.orderPizza("cheese");
}

这样既能根据地域生产不同口味披萨,同时严格执行披萨制作流程。

认识与定义工厂方法模式

所有工厂模式都是用来封装对象的创建。工厂方法模式(Factory Method Pattern)通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。

创建者(Creator)类

抽象创建者类,定义了一个抽象的工厂方法,让子类实现此方法制造产品。

产品类

这是具体的产品,所有店里能实际制造的披萨在这里实现。

根据上面披萨店一系列的演变,很清楚地可以看出,在代码里减少对于具体类的依赖是件好事。事实上,有一个OO设计原则就正式阐明了这一点,即依赖倒置原则。

设计原则:

要依赖抽象,不要依赖具体。

不能让高层组件依赖底层组件,而且,不管高层或底层组件,两者都应该依赖抽象。

使用工厂方法之后,高层组件和底层组件都依赖了Pizza抽象。

第三部分,抽象工厂模式

再回到披萨店

现在披萨店的设计变得很棒,具有弹性的框架,而且遵循设计原则。现在加盟店都遵循你制定的设计流程,但是有一些加盟店,使用低价的原料来增加利润。你必须采取一些手段,以免长此以往毁了自己披萨店的招牌。

你打算确保每一家加盟店使用高质量的原料,因此打算建造一家生产原料的工厂,并将原料运送到各家加盟店。

但是每一个地区制作披萨用到的原料不一样。

所以,你打算根据地区不同,建立不同的原料家族。

建造原料工厂

现在建造一个原料工厂来生产原料,这个工厂将负责创建原料家族中的每一种原料。即这个工厂需要生产面团、酱料、芝士。

public class PizzaIngredientFactory {
public Dough createDough();
   public Sauce createSauce();
   public Cheese createCheese();
   public Veggies[] createVeggies();
   public Pepperoni createPepperoni();
   public Clams createClam();
}

创建纽约原料工厂

public class NYPizzaIngredientFactory implemes PizzaIngredientFactory {
public Dough createDough() {
       return new ThinCrustDough();
  }
   public Sauce createSauce() {
       return new MarinaraSauce();
  }
   public Cheese createCheese() {
       return new ReggianoCheese();
  }
   public Veggies[] createVeggies() {
       Veggies vegggies[] = {new Garlic(), new Onion(), new Mushroom(), new RedPepper()}
       return veggies;
  }
   public Pepperoni createPepperoni() {
       return new SlicedPepperoni();
  }
   public Clams createClam() {
return new FreshClams();
  }
}

现在,我们不需要设计两个不同的类来处理不同风味的披萨了,直接让原料工厂处理这种地域差异就可以了。

蛤蜊披萨实现

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

纽约披萨加盟店

public class NYPizzaStore extends PizzaStore {  
protected Pizza createPizza(String type) {
Pizza pizza = null;
       PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();

       // 根据不同的类型,创建不同的披萨
       if (type.equals("cheese")) {
      pizza = new CheesePizza(ingredientFactory);
           pizza.setName("New York Style Cheese Pizza")
      } else if (type.equals("greek")) {
      pizza = new GreekPizza(ingredientFactory);
           pizza.setName("New York Style greek Pizza")
      } else if (type.equals("pepperoni")) {
      pizza = new PepperoniPizza(ingredientFactory);
           pizza.setName("New York Style pepperoni Pizza")
      }
       return pizza;
}
}

定义抽象工厂模式

抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

即抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么。

标签:披萨,模式,工厂,new,Pizza,type,public,pizza
From: https://www.cnblogs.com/l12138h/p/16983564.html

相关文章

  • JavaScript学习--Item1 严格模式
    一、概述除了正常运行模式,ECMAscript5添加了第二种运行模式:“严格模式”(strictmode)。顾名思义,这种模式使得Javascript在更严格的条件下运行。设立”严格模式”的目的,主要......
  • 行为型:设计模式之解释器模式(二十二)
     虽然目前计算机编程语言有好几百种,但有时候我们还是希望能用一些简单的语言来实现一些特定的操作,我们只要向计算机输入一个句子或文件,它就能够按照预先定义的文法规则来对......
  • 行为型:设计模式之迭代器模式(二十一)
     20世纪80年代,那时我家有一台“古老的”电视机,牌子我忘了,只记得是台黑白电视机,没有遥控器,每次开关机或者换台都需要通过电视机上面的那些按钮来完成,我印象最深的是那个用来......
  • 【设计模式】行为型模式之命令模式
    三个角色命令发出者,命令,命令执行者解决的问题降低命令发出者和命令执行者之间的耦合度理解假设在饭店的场景下,服务员(命令发出者)会把客人点的菜写在一张纸上(......
  • 结构型:设计模式之适配器模式(六)
    20V,而我国的家庭用电是220V,如何让20V的笔记本电脑能够在220V的电压下工作?答案是引入一个电源适配器(ACAdapter),俗称充电器或变压器,有了这个电源适配器,生活用电和笔记本电脑......
  • 创建型:设计模式之建造模式(四)
     没有人买车会只买一个轮胎或者方向盘,大家买的都是一辆包含轮胎、方向盘和发动机等多个部件的完整汽车。如何将这些部件组装成一辆完整的汽车并返回给用户,这是建造者模式需......
  • 单例模式的七种写法
    第一种(懒汉,线程不安全): 1 public class Singleton {   2     private static Singleton instance;   3 private Singleton......
  • Cesium地下模式
    Cesium地下模式在一般的业务场景中,例如地下管线这些需要看地下模型的场景时候,需要开启地下模式。而开启地下模式也非常简单开启地下模式注释可见constenterUnderGrou......
  • ros的一些模式safemode
    ctrl+c中断模式ctrl+x进入/退出安全模式,如果你这个时候网络中断则不会保存你刚才敲的命令。F7进入hotlock模式,命令自动完成,不用按tab键ctrl+d注销回话同时撤销所有安全......
  • 迭代器模式
    迭代器模式被迭代对象接口packageiteratortypeAggregateinterface{createIterator()Iterator}具体被迭代的对象packageiteratortypearray[]int......