开篇

天天逛博客园,就是狠不下心来写篇博客,忙是一方面,但是说忙能有多忙呢,都有时间逛博客园,写篇博客的时间都没有?(这还真不好说)

每次想到写一篇新的设计模式,我总会问自己:

1,自己理解了吗?

2,我能以一种简单且有逻辑的方式把它说出来吗?

不说做到有的放矢,但是一本正经的胡说八道还是要有吧,起码要忽悠得头头是道嘛(手动斜眼笑)

关于工厂模式的几个问题

1,这个是拿来干什么的?

2,怎么用?

3,不用行不行?

第一个和第三个问题,我现在就可以告诉你答案:早点下班,可以

所有的设计模式对我来说都是为了减少工作量。关于减少工作量我的理解是:每个需求,都应该在它适当的时候出现适当的代码!这个太重要了

代码偷懒,后期返工多

过度设计,后期返工多

设计模式+经验可以解决这个问题,其他的我还不知道。没有经验怎么办?两个要点:

1,能用

2,简洁

首先要达到能用,然后就是尽量简洁,这样代码就不会太差。首先你要自己看得懂,然后是让队友看得懂。

你知道你队友看到一堆烂的看都看不懂,也一句注释都没有的代码的时候的心理阴影面积吗?

这其实也没什么,谁没填过别人的坑呢?关键是他知道你家在哪里,而且还知道你经常走夜路,就问你怕不怕?(卧槽,又跑题了。。)

需求:你有一个披萨店,只卖一种披萨,代码如下:

披萨:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. /**
  5. * 披萨类
  6. * @author skysea
  7. */
  8. public class Pizza {
  9.  
  10. private String name;//披萨名称
  11.  
  12. private String dough;//面团
  13.  
  14. private String sauce;//酱料
  15.  
  16. private List<String> toppings = new ArrayList<>();//佐料
  17.  
  18. public Pizza() {
  19. this.name = "原味披萨";
  20. this.dough = "原味面团";
  21. this.sauce = "原味酱料";
  22. }
  23.  
  24. void prepare() {
  25. System.out.println("开始准备披萨:" + name);
  26.  
  27. System.out.println("开始处理面团:" + dough);
  28.  
  29. System.out.println("添加酱料:" + sauce);
  30.  
  31. System.out.println("添加佐料:");
  32. if(toppings.size() > 0) {
  33. for(String t : toppings) {
  34. System.out.println(" " + t);
  35. }
  36. }
  37. }
  38.  
  39. void bake() {
  40. System.out.println("烘焙25分钟..");
  41. }
  42.  
  43. void cut() {
  44. System.out.println("披萨切片..");
  45. }
  46.  
  47. void box() {
  48. System.out.println("披萨打包..");
  49. }
  50.  
  51. public String getName() {
  52. return name;
  53. }
  54. }

披萨店:

  1. /**
  2. * 只卖一种披萨的披萨店
  3. * @author skysea
  4. */
  5. public class PizzaStore {
  6.  
  7. public Pizza orderPizza() {
  8. Pizza pizza = new Pizza();
  9. pizza.prepare();
  10. pizza.bake();
  11. pizza.cut();
  12. pizza.box();
  13. return pizza;
  14. }
  15. }

测试类:

  1. /**
  2. * pizza测试类
  3. * @author skysea
  4. */
  5. public class PizzaTest {
  6. public static void main(String[] args) {
  7. PizzaStore pizzaStore = new PizzaStore();
  8. Pizza pizza = pizzaStore.orderPizza();
  9. System.out.println("当前预定的披萨:" + pizza.getName());
  10. }
  11. }

现在披萨店要拓展业务了,因为卖一种披萨顾客已经吃腻了,现在要开始添加新的披萨类型

简单工厂模式

Pizza类的改进

  1. import java.util.ArrayList;
  2. import java.util.List;
  3.  
  4. /**
  5. * 披萨抽象类
  6. * 1,修改private -> protected(保证子类拥有这些属性)
  7. * 2,将Pizza定义为abstract类,防止被new,也是为后面的改造做准备
  8. * @author skysea
  9. */
  10. public abstract class Pizza {
  11.  
  12. protected String name;//披萨名称
  13.  
  14. protected String dough;//面团
  15.  
  16. protected String sauce;//酱料
  17.  
  18. protected List<String> toppings = new ArrayList<>();//佐料
  19.  
  20. void prepare() {
  21. System.out.println("开始准备披萨:" + name);
  22.  
  23. System.out.print("开始处理面团:" + dough);
  24.  
  25. System.out.println("添加酱料:" + sauce);
  26.  
  27. System.out.println("添加佐料:");
  28. for(String t : toppings) {
  29. System.out.println(" " + t);
  30. }
  31. }
  32.  
  33. void bake() {
  34. System.out.println("烘焙25分钟..");
  35. }
  36.  
  37. void cut() {
  38. System.out.println("披萨切片..");
  39. }
  40.  
  41. void box() {
  42. System.out.println("披萨打包..");
  43. }
  44.  
  45. public String getName() {
  46. return name;
  47. }
  48.  
  49. @Override
  50. public String toString() {
  51. return "Pizza [name=" + name + ", dough=" + dough + ", sauce=" + sauce + ", toppings=" + toppings + "]";
  52. }
  53. }

先给出新增的披萨

芝士披萨:

  1. /**
  2. * 芝士披萨
  3. * @author skysea
  4. */
  5. public class CheesePizza extends Pizza{
  6. public CheesePizza() {
  7. this.name = "芝士披萨";
  8. this.dough = "芝士披萨的面团";
  9. this.sauce = "芝士披萨的酱料";
  10. this.toppings.add("很多芝士....");
  11. }
  12. }

蛤蜊披萨:

  1. /**
  2. * 蛤蜊披萨
  3. * @author skysea
  4. */
  5. public class ClamPizza extends Pizza {
  6. public ClamPizza() {
  7. this.name = "蛤蜊披萨";
  8. this.dough = "蛤蜊披萨的面团";
  9. this.sauce = "蛤蜊披萨的酱料";
  10. this.toppings.add("蛤蜊");
  11. }
  12. }

意大利烤肠披萨:

  1. /**
  2. * 意大利烤肠披萨
  3. * @author skysea
  4. */
  5. public class PepperoniPizza extends Pizza{
  6.  
  7. public PepperoniPizza() {
  8. this.name = "意大利烤肠披萨";
  9. this.dough = "意大利烤肠披萨的面团";
  10. this.sauce = "意大利烤肠披萨的酱料";
  11. this.toppings.add("一大波意大利烤肠...");
  12. }
  13. }

素食比萨:

  1. /**
  2. * 素食比萨
  3. * @author skysea
  4. */
  5. public class VeggiePizza extends Pizza {
  6. public VeggiePizza() {
  7. name = "素食比萨";
  8. dough = "素食比萨的面团";
  9. sauce = "素食比萨的酱料";
  10. toppings.add("素食比萨");
  11. toppings.add("素食比萨佐料1");
  12. toppings.add("素食比萨佐料2");
  13. }
  14. }

贴了这么多代码,先给出一波简单的实现:

  1. /**
  2. * pizza店
  3. * @author skysea
  4. */
  5. public class PizzaStore {
  6.  
  7. public Pizza orderPizza(String type) {
  8. Pizza pizza = null;
  9. if (type.equals("cheese")) {
  10. pizza = new CheesePizza();
  11. } else if (type.equals("pepperoni")) {
  12. pizza = new PepperoniPizza();
  13. } else if (type.equals("clam")) {
  14. pizza = new ClamPizza();
  15. } else if (type.equals("veggie")) {
  16. pizza = new VeggiePizza();
  17. }
  18.  
  19. pizza.prepare();
  20. pizza.bake();
  21. pizza.cut();
  22. pizza.box();
  23.  
  24. return pizza;
  25. }
  26.  
  27. }

在不考虑继续扩展披萨种类的时候,这样的实现有没有问题,一般来说,达到了可以用的标准,但是不好用,问题如下:

1,没有兼容原来的一种披萨方法 public Pizza orderPizza(),相信我,每一个public方法都是很重要的,因为你不知道有多少地方用到过。当然也不是没办法知道,只是你知道也不一定就能改,就算你能改,也不一定改对。

2,String类型的type太容易出错了,个人感觉对程序开发不友好,当然这个也要分情况,灵活和严谨本来就很难做到两全

3,推荐取不到合适的type时抛异常,而不是返回空,便于排查问题(此处的if里面只是直接new返回的对象,实际情况远比现在的复杂)

给出第二版:

  1. /**
  2. * pizza店
  3. * @author skysea
  4. */
  5. public class PizzaStore {
  6.  
  7. public Pizza orderPizza() {
  8. return orderPizza(PizzaTypeEnum.CHEESE);
  9. }
  10.  
  11. public Pizza orderPizza(PizzaTypeEnum type) {
  12. Pizza pizza;
  13.  
  14. pizza = SimplePizzaFactory.getPizza(type);
  15. pizza.prepare();
  16. pizza.bake();
  17. pizza.cut();
  18. pizza.box();
  19.  
  20. return pizza;
  21. }
  22. }

SimplePizzaFactory:

  1. /**
  2. * 简单工厂类
  3. * @author skysea
  4. */
  5. public class SimplePizzaFactory {
  6.  
  7. /**
  8. * 根据类型获取pizza
  9. * @param type
  10. * @return
  11. */
  12. public static final Pizza getPizza(PizzaTypeEnum type){
  13. switch (type) {
  14. case CHEESE: return new CheesePizza();
  15. case CLAM: return new ClamPizza();
  16. case PEPPERONI: return new PepperoniPizza();
  17. case VEGGIE: return new VeggiePizza();
  18. default: throw new NoSuchPizzaException(type.getCode());
  19. }
  20. }
  21. }

辅助类(枚举,异常):

  1. /**
  2. * 定义pizza类型枚举
  3. * @author skysea
  4. *
  5. */
  6. public enum PizzaTypeEnum{
  7. /**
  8. * 芝士披萨
  9. */
  10. CHEESE("cheese"),
  11. /**
  12. * 意大利烤肠披萨
  13. */
  14. PEPPERONI("pepperoni"),
  15. /**
  16. * 蛤蜊披萨
  17. */
  18. CLAM("clam"),
  19. /**
  20. * 素食比萨
  21. */
  22. VEGGIE("veggie");
  23. private final String code;
  24. PizzaTypeEnum(String code) {
  25. this.code = code;
  26. }
  27. public String getCode() {
  28. return code;
  29. }
  30. }
  1. /**
  2. * 没有匹配的pizza异常
  3. * @author skysea
  4. */
  5. public class NoSuchPizzaException extends RuntimeException{
  6. private static final long serialVersionUID = 6831396172306375611L;
  7. public NoSuchPizzaException(String message) {
  8. super(message);
  9. }
  10. }

测试类:

  1. /**
  2. * pizza测试类
  3. * @author skysea
  4. */
  5. public class PizzaTest {
  6.  
  7. public static void main(String[] args) {
  8. PizzaStore store = new PizzaStore();
  9.  
  10. Pizza pizza = store.orderPizza(PizzaTypeEnum.CHEESE);
  11. System.out.println(pizza);
  12.  
  13. pizza = store.orderPizza(PizzaTypeEnum.VEGGIE);
  14. System.out.println(pizza);
  15. }
  16. }

好了,代码写到这里,其实对于:新增披萨类型的这个需求的实现其实已经很好了。至少来说现阶段的需求实现了,其次就是对调用方友好,至少队友不会跑过来问你类型传啥,不会告诉你他string字符串传错了,不会在你改个类型的时候,还要通知他(当然这个也可以通过常量来处理)。

吹了半天,来说说这段代码的问题,正常情况下,需求会是这样变:

1,PepperoniPizza暂时不要了,一般来说,你问他要不要,他会说,这个要看后面的运营情况(我:...)

2,你给我新加一个xx披萨

现在需要改的是两个地方,一个是工厂类,一个是枚举,但是主要的流程是不用改了,如果你觉得还是很麻烦在不考虑性能的情况下,你还可以用反射来玩,改造一下工厂类(实现通过class来创建对象)和枚举(添加一个字段来存放type对应的class)就可以了,不赘述..

第一波需求就差不多可以这样收手了,随着业务的发展,披萨店那叫一个红火啊,虽然中间也对代码做了很多新的披萨,但是由于PizzaStore相当稳定,也没出什么大问题。

新的问题(开分店):

1,旗舰店在芝加哥,现在要在纽约开一家新的店

2,分店的披萨口味要根据当地的口味来进行调整,保证能够不失品牌特色的同时,也能满足当地独特的风味

3,分店披萨的种类与暂时与旗舰店保持一致

工厂方法模式

先把所有的披萨列出来

芝加哥的披萨:

  1. /**
  2. * 芝加哥芝士披萨
  3. * @author skysea
  4. */
  5. public class ChicagoStyleCheesePizza extends Pizza {
  6.  
  7. public ChicagoStyleCheesePizza() {
  8. name = "芝加哥芝士披萨";
  9. dough = "芝加哥芝士披萨面团";
  10. sauce = "芝加哥芝士披萨酱料";
  11.  
  12. toppings.add("芝加哥芝士披萨调料1");
  13. toppings.add("芝加哥芝士披萨调料2");
  14. }
  15.  
  16. @Override
  17. void cut() {
  18. System.out.println("芝加哥芝士披萨版切片...");
  19. }
  20. }
  21. /**
  22. * 芝加哥蛤蜊披萨
  23. * @author skysea
  24. */
  25. public class ChicagoStyleClamPizza extends Pizza {
  26. public ChicagoStyleClamPizza() {
  27. name = "芝加哥蛤蜊披萨";
  28. dough = "芝加哥蛤蜊披萨面团";
  29. sauce = "芝加哥蛤蜊披萨酱料";
  30.  
  31. toppings.add("芝加哥蛤蜊披萨佐料1");
  32. toppings.add("芝加哥蛤蜊披萨佐料2");
  33. }
  34.  
  35. @Override
  36. void cut() {
  37. System.out.println("芝加哥蛤蜊披萨版切片...");
  38. }
  39. }
  40. /**
  41. * 芝加哥意大利烤肠披萨
  42. * @author skysea
  43. */
  44. public class ChicagoStylePepperoniPizza extends Pizza {
  45. public ChicagoStylePepperoniPizza() {
  46. name = "芝加哥意大利烤肠披萨";
  47. dough = "芝加哥意大利烤肠披萨面团";
  48. sauce = "芝加哥意大利烤肠披萨酱料";
  49.  
  50. toppings.add("芝加哥意大利烤肠披萨调料1");
  51. toppings.add("芝加哥意大利烤肠披萨调料2");
  52. toppings.add("芝加哥意大利烤肠披萨调料3");
  53. toppings.add("芝加哥意大利烤肠披萨调料4");
  54. }
  55.  
  56. @Override
  57. void cut() {
  58. System.out.println("芝加哥意大利烤肠披萨版切片...");
  59. }
  60. }
  61. /**
  62. * 芝加哥素食比萨
  63. * @author skysea
  64. */
  65. public class ChicagoStyleVeggiePizza extends Pizza {
  66. public ChicagoStyleVeggiePizza() {
  67. name = "芝加哥素食比萨";
  68. dough = "芝加哥素食比萨的面团";
  69. sauce = "芝加哥素食比萨的酱料";
  70.  
  71. toppings.add("芝加哥素食比萨调料1");
  72. toppings.add("芝加哥素食比萨调料2");
  73. toppings.add("芝加哥素食比萨调料3");
  74. }
  75.  
  76. void cut() {
  77. System.out.println("芝加哥素食比萨版切片...");
  78. }
  79. }

纽约的披萨:

  1. /**
  2. * 纽约芝士披萨
  3. * @author skysea
  4. */
  5. public class NYStyleCheesePizza extends Pizza {
  6.  
  7. public NYStyleCheesePizza() {
  8. name = "纽约芝士披萨";
  9. dough = "纽约芝士披萨面团";
  10. sauce = "纽约芝士披萨酱料";
  11.  
  12. toppings.add("纽约芝士披萨调料1");
  13. toppings.add("纽约芝士披萨调料2");
  14. }
  15.  
  16. @Override
  17. void cut() {
  18. System.out.println("纽约芝士披萨版切片...");
  19. }
  20. }
  21. /**
  22. * 纽约蛤蜊披萨
  23. * @author skysea
  24. */
  25. public class NYStyleClamPizza extends Pizza {
  26. public NYStyleClamPizza() {
  27. name = "纽约蛤蜊披萨";
  28. dough = "纽约蛤蜊披萨面团";
  29. sauce = "纽约蛤蜊披萨酱料";
  30.  
  31. toppings.add("纽约蛤蜊披萨佐料1");
  32. toppings.add("纽约蛤蜊披萨佐料2");
  33. }
  34.  
  35. @Override
  36. void cut() {
  37. System.out.println("纽约蛤蜊披萨版切片...");
  38. }
  39. }
  40. /**
  41. * 纽约意大利烤肠披萨
  42. * @author skysea
  43. */
  44. public class NYStylePepperoniPizza extends Pizza {
  45. public NYStylePepperoniPizza() {
  46. name = "纽约意大利烤肠披萨";
  47. dough = "纽约意大利烤肠披萨面团";
  48. sauce = "纽约意大利烤肠披萨酱料";
  49.  
  50. toppings.add("纽约意大利烤肠披萨调料1");
  51. toppings.add("纽约意大利烤肠披萨调料2");
  52. toppings.add("纽约意大利烤肠披萨调料3");
  53. toppings.add("纽约意大利烤肠披萨调料4");
  54. }
  55.  
  56. @Override
  57. void cut() {
  58. System.out.println("纽约意大利烤肠披萨版切片...");
  59. }
  60. }
  61. /**
  62. * 纽约素食比萨
  63. * @author skysea
  64. */
  65. public class NYStyleVeggiePizza extends Pizza {
  66. public NYStyleVeggiePizza() {
  67. name = "纽约素食比萨";
  68. dough = "纽约素食比萨的面团";
  69. sauce = "纽约素食比萨的酱料";
  70.  
  71. toppings.add("纽约素食比萨调料1");
  72. toppings.add("纽约素食比萨调料2");
  73. toppings.add("纽约素食比萨调料3");
  74. }
  75.  
  76. void cut() {
  77. System.out.println("纽约素食比萨版切片...");
  78. }
  79. }

披萨倒是列完了,但是在实际的开发过程中,业务逻辑这么简单那是不可能的,想要改那什么旗舰店披萨的类名是很困难的

一般要考虑:

1,是不是单机,有没有其他外部系统在调用

2,改动原来的代码有什么好处,更容易理解吗?迭代了几个版本过后垃圾代码太多了吗?

3,影响大不大

当然,我这里是随便造,你们呢,我就不知道了,嘿嘿嘿,所以碰到这种情况,一般来说要悠着点,看时间,也要看影响,开发就是这样,同一个功能,2天有2天的做法,5天有5天的做法,10天有10天的做法

披萨店改造:

  1. /**
  2. * 披萨店抽象类
  3. * @author skysea
  4. */
  5. public abstract class PizzaStore {
  6.  
  7. abstract Pizza createPizza(String item);
  8.  
  9. public Pizza orderPizza(String type) {
  10. Pizza pizza = createPizza(type);
  11. System.out.println("--- 制作 " + pizza.getName() + " ---");
  12. pizza.prepare();
  13. pizza.bake();
  14. pizza.cut();
  15. pizza.box();
  16. return pizza;
  17. }
  18. }
  1. /**
  2. * 芝加哥披萨店
  3. * @author skysea
  4. */
  5. public class ChicagoPizzaStore extends PizzaStore {
  6. public static final String CHEESE = "cheese";
  7. public static final String VEGGIE = "veggie";
  8. public static final String CLAM = "clam";
  9. public static final String PEPPERONI = "pepperoni";
  10. Pizza createPizza(String item) {
  11. if (CHEESE.equals(item)) {
  12. return new ChicagoStyleCheesePizza();
  13. } else if (VEGGIE.equals(item)) {
  14. return new ChicagoStyleVeggiePizza();
  15. } else if (CLAM.equals(item)) {
  16. return new ChicagoStyleClamPizza();
  17. } else if (PEPPERONI.equals(item)) {
  18. return new ChicagoStylePepperoniPizza();
  19. } else {
  20. throw new NoSuchPizzaException(item);
  21. }
  22. }
  23. }

纽约披萨店(和芝加哥披萨店几乎一毛一样,这里就不展开了):

  1. /**
  2. * 纽约披萨店
  3. * @author skysea
  4. */
  5. public class NYPizzaStore extends PizzaStore {
  6.  
  7. public static final String CHEESE = "cheese";
  8. public static final String VEGGIE = "veggie";
  9. public static final String CLAM = "clam";
  10. public static final String PEPPERONI = "pepperoni";
  11. Pizza createPizza(String item) {
  12. if (CHEESE.equals(item)) {
  13. return new NYStyleCheesePizza();
  14. } else if (VEGGIE.equals(item)) {
  15. return new NYStyleVeggiePizza();
  16. } else if (CLAM.equals(item)) {
  17. return new NYStyleClamPizza();
  18. } else if (PEPPERONI.equals(item)) {
  19. return new NYStylePepperoniPizza();
  20. } else {
  21. throw new NoSuchPizzaException(item);
  22. }
  23. }
  24. }

这段代码有三个问题要理解清楚:

1,这个地方为啥要弄个抽象类出来?

这个就要结合实际来理解了,分店与分店之间,需不需要统一规范化管理?需不需要保证自己的特色?答案毫无疑问,都是需要的

这个地方制作披萨的过程,毫无疑问是肯定要一致的。就像外卖一样,下单,炒菜,配送。整套流程都是这样,不能说你出来就开始炒菜了啊,这不科学。不一样的地方就是,你炒的什么菜,好不好吃。配送得快不快,稳不稳,服务好不好。

所以,抽象类的意义就是:规范、特色

2,factory咋个不见了?

因为把它和具体的store合并在一起了,这样又引申出另外一个问题:为啥要合并?因为store现在充当的角色就是facotry,刚才说过的制作过程已经放到父类中实现了,现在只需要在具体的store中去解决披萨的创建问题

3,为啥又不用枚举了,弄个String来创建pizza?

如果还是单机,用枚举当然会比直接扔个string来得稳当。

开了分店,要是每个分店都是一套完整的服务在玩,丢个string,要比枚举来得好。原因有2:传输过程中的序列化和反序列化、更加灵活(客户端不用每次都因为这个原因要去升级对应的包,特别是多个版本在跑得时候,升级了又会导致其他东西不能玩)

测试类:

  1. /**
  2. * 披萨测试类
  3. * @author skysea
  4. */
  5. public class PizzaTest {
  6.  
  7. public static void main(String[] args) {
  8. PizzaStore nyStore = new NYPizzaStore();
  9. PizzaStore chicagoStore = new ChicagoPizzaStore();
  10.  
  11. Pizza pizza = nyStore.orderPizza(NYPizzaStore.CHEESE);
  12. System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  13.  
  14. pizza = chicagoStore.orderPizza(ChicagoPizzaStore.CHEESE);
  15. System.out.println("Joel ordered a " + pizza.getName() + "\n");
  16.  
  17. pizza = nyStore.orderPizza(NYPizzaStore.CLAM);
  18. System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  19.  
  20. pizza = chicagoStore.orderPizza(ChicagoPizzaStore.CLAM);
  21. System.out.println("Joel ordered a " + pizza.getName() + "\n");
  22.  
  23. pizza = nyStore.orderPizza(NYPizzaStore.PEPPERONI);
  24. System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  25.  
  26. pizza = chicagoStore.orderPizza(ChicagoPizzaStore.PEPPERONI);
  27. System.out.println("Joel ordered a " + pizza.getName() + "\n");
  28.  
  29. pizza = nyStore.orderPizza(NYPizzaStore.VEGGIE);
  30. System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  31.  
  32. pizza = chicagoStore.orderPizza(ChicagoPizzaStore.VEGGIE);
  33. System.out.println("Joel ordered a " + pizza.getName() + "\n");
  34. }
  35. }

结果(结果太多了,就不全部截图出来了):


headfirst设计模式(4)—工厂模式的更多相关文章

  1. HeadFirst设计模式之工厂模式

    一. 1."工厂模式"不是种真正的设计模式,而是一种编程术语 2.The Factory Method Pattern defi nes an interface for crea ...

  2. HeadFirst 设计模式 04 工厂模式

    除了 new 操作符之外, 还有更多创造对象的方法. 工厂处理创建对象的细节. 这么做的目的是为了抽象, 例如把创建比萨的代码包装进一个类, 当以后实现改变时, 只需修改这个类即可. 利用静态方法定义 ...

  3. 设计模式——抽象工厂模式及java实现

    设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...

  4. 5. 星际争霸之php设计模式--抽象工厂模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  5. 3. 星际争霸之php设计模式--简单工厂模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  6. iOS 设计模式之工厂模式

    iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...

  7. 设计模式之工厂模式(Factory)

    设计模式的工厂模式一共有三种:简单工厂模式,工厂模式,抽象工厂模式 简单工厂模式原理:只有一个工厂类,通过传参的形式确定所创建的产品对象种类 代码如下: #include <stdio.h> ...

  8. php设计模式:工厂模式

    php设计模式:工厂模式 意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类. 工厂模式实现: 工厂模式中任何创建对象的工厂类都要实现这个接口,实现接口的方法体中都要实现接口中的方法,它声明 ...

  9. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  10. java 设计模式之工厂模式与反射的结合

    工厂模式: /**  * @author Rollen-Holt 设计模式之 工厂模式  */   interface fruit{     public abstract void eat(); } ...

随机推荐

  1. 使用ztree展示树形菜单结构

    官网:http://www.treejs.cn/v3/main.php#_zTreeInfo 一.功能简介 在权限系统中,实现给角色指定菜单权限的功能.主要包括以下几点: 读取全部菜单项,并以树形结构 ...

  2. asp.net core 实现一个简单的仓储

    一直有自己写个框架的想法,但是一直没有行动起来,最近比较闲,正好可以开工了. 现在已经完成了两部分.1.一个简单仓储,实现使用的是ef 2.IOC部分,这里是把内置的ioc替换成了aotofac,这部 ...

  3. 「JavaScript」手起刀落-一起来写经典的贪吃蛇游戏

    回味 小时候玩的经典贪吃蛇游戏我们印象仍然深刻,谋划了几天,小时候喜欢玩的游戏,长大了终于有能力把他做出来(从来都没有通关过,不知道自己写的程序,是不是能通关了...),好了,闲话不多谈,先来看一下效 ...

  4. python3.5安装pyHook,解决【TypeError: MouseSwitch() missing 8 required positional arguments: 'msg', 'x', 'y', 'data', 'time', 'hwnd', and 'window_name'】这个错误!

    为什么安装 pyHook包:为Windows中的全局鼠标和键盘事件提供回调. Python应用程序为用户输入事件注册事件处理程序,例如鼠标左键,鼠标左键,键盘键等 先要实时获取系统的鼠标位置或者键盘输 ...

  5. [C#]使用GroupJoin将两个关联的集合进行分组

    本文为原创文章.源代码为原创代码,如转载/复制,请在网页/代码处明显位置标明原文名称.作者及网址,谢谢! 本文使用的开发环境是VS2017及dotNet4.0,写此随笔的目的是给自己及新开发人员作为参 ...

  6. Linux 链接详解----动态链接库

    静态库的缺点: 库函数被包含在每一个运行的进程中,会造成主存的浪费. 目标文件的size过大 每次更新一个模块都需要重新编译,更新困难,使用不方便. 动态库: 是一个目标文件,包含代码和数据,它可以在 ...

  7. Android开发之漫漫长途 番外篇——内存泄漏分析与解决

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. NYOJ 323 Drainage Ditches 网络流 FF 练手

    Drainage Ditches 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 Every time it rains on Farmer John's fields, ...

  9. How to get table pg_stat_user_functions.

    修改配置文件postgres.conf track_functions = all                   # none, pl, all 或者 在当前事物中设置 postgres=# s ...

  10. .Net Core实现将文件上传到七牛云存储

    功能:将图片上传到七牛云存储 准备工作 注册七牛账号,提交实名认证(基本上1天内内审核通过) 登录七牛后台->对象存储->新建空间 (基本概念:https://developer.qini ...