黑马Java面试教程_P10_设计模式

打印 上一主题 下一主题

主题 987|帖子 987|积分 2961

系列博客目录



  

媒介

在平常的开辟中,涉及到设计模式的有两块内容,第一个是我们平常使用的框架(好比spring、mybatis等),第二个是我们自己开辟业务使用的设计模式。
面试官一般比力关心的是你在开辟过程中,有没有使用过设计模式,大概你在简历上写了关于设计模式的形貌,那么这样我们就必要重点关心自己开辟中用过的设计模式。
在平常的业务开辟中,实在真正使用设计模式的场景并不多,固然设计号称有23种之多(差别的纬度大概会更多),但是在项目最常使用的也就几种而已,在面试的过程中,我们主要先容一种或两种就可以,重点要说的是:在什么业务场景下使用了设计模式,什么设计模式?

这次面试部分,我们主要先容三种设计模式:


  • 工厂方法模式(简朴工厂、工厂方法、抽象工厂)
  • 策略模式(讲完后与前一个模式合起来讲一个案例)
  • 责任链模式(单独讲一个案例)
1. 工厂方法模式

1.1 概述

需求:设计一个咖啡店点餐系统。
设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
具体类的设计如下:

   1.类图中的符号
  

  • +:表现public
  • -:表现private
  • #:表现protected
  2.泛化关系(继承)用带空心三角箭头的实线来表现
3.依赖关系使用带箭头的虚线来表现
4.实现关系用带空心的三角箭头的虚线来表现
  选择差别咖啡代码如下:
  1. package com.itheima.factory.simple;
  2. public class CoffeeStore {
  3.      public static void main(String[] args) {
  4.          Coffee coffee = orderCoffee("latte");
  5.          System.out.println(coffee.getName());
  6.      }
  7.      public static Coffee orderCoffee(String type){
  8.          Coffee coffee = null;
  9.          if("american".equals(type)){
  10.              coffee = new AmericanCoffee();
  11.          }else if ("latte".equals(type)){
  12.              coffee = new LatteCoffee();
  13.          }
  14.          //添加配料
  15.          coffee.addMilk();
  16.          coffee.addSuqar();
  17.          return coffee;
  18.      }
  19. }
复制代码
在java中,万物皆对象,这些对象都必要创建,假如创建的时候直接new该对象,就会对该对象耦合严峻,假如我们要更换对象,所有new对象的地方都必要修改一遍,这显然违背了软件设计的开闭原则。假如我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,假如要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦
   开闭原则:对扩展开放,对修改关闭。在程序必要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。
  三种工厂


  • 简朴工厂模式
  • 工厂方法模式
  • 抽象工厂模式
1.2 简朴工厂模式

简朴工厂不是一种设计模式,反而比力像是一种编程风俗。
1.2.1 结构

简朴工厂包含如下角色:


  • 抽象产品 :定义了产品的规范,形貌了产品的主要特性和功能。
  • 具体产品 :实现大概继承抽象产品的子类
  • 具体工厂 :提供了创建产品的方法,调用者通过该方法来获取产品。
1.2.2 实现

现在使用简朴工厂对上面案例进行改进,类图如下:

  1. public class SimpleCoffeeFactory {
  2.      public Coffee createCoffee(String type) {
  3.          Coffee coffee = null;
  4.          if("americano".equals(type)) {
  5.              coffee = new AmericanoCoffee();
  6.          } else if("latte".equals(type)) {
  7.              coffee = new LatteCoffee();
  8.          }
  9.          return coffee;
  10.      }
  11. }
复制代码
工厂(factory)处理惩罚创建对象的细节,一旦有了SimpleCoffeeFactory,CoffeeStore类中的orderCoffee()就变成此对象的客户,后期假如必要Coffee对象直接从工厂中获取即可。这样也就解除了和Coffee实现类的耦合,同时又产生了新的耦合,CoffeeStore对象和SimpleCoffeeFactory工厂对象的耦合,工厂对象和商品对象的耦合。
后期假如再加新品种的咖啡,我们势必要需求修改SimpleCoffeeFactory的代码,违背了开闭原则。工厂类的客户端大概有很多,好比创建美团外卖等,这样只必要修改工厂类的代码,省去其他的修改操纵。
1.2.3 优缺点

优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,假如要实现新产品直接修改工厂类,而不必要在原代码中修改,这样就降低了客户代码修改的大概性,更加容易扩展。
缺点:
增长新产品时照旧必要修改工厂类的代码,违背了“开闭原则”。
1.3 工厂方法模式

针对上例中的缺点,使用工厂方法模式就可以完善的办理,完全遵循开闭原则。
1.3.1 概念

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
1.3.2 结构

工厂方法模式的主要角色:


  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,形貌了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间逐一对应。
1.3.3 实现


流程:

代码如下:
抽象工厂:
  1. public interface CoffeeFactory {
  2.      Coffee createCoffee();
  3. }
复制代码
具体工厂:
  1. public class LatteCoffeeFactory implements CoffeeFactory {
  2.      public Coffee createCoffee() {
  3.          return new LatteCoffee();
  4.      }
  5. }
  6. public class AmericanCoffeeFactory implements CoffeeFactory {
  7.      public Coffee createCoffee() {
  8.          return new AmericanCoffee();
  9.      }
  10. }
复制代码
咖啡店类:
  1. public class CoffeeStore {
  2.      private CoffeeFactory factory;
  3.      public CoffeeStore(CoffeeFactory factory) {
  4.          this.factory = factory;
  5.      }
  6.      public Coffee orderCoffee(String type) {
  7.          Coffee coffee = factory.createCoffee();
  8.          coffee.addMilk();
  9.          coffee.addsugar();
  10.          return coffee;
  11.      }
  12. }
复制代码
从以上的编写的代码可以看到,要增长产品类时也要相应地增长工厂类,不必要修改工厂类的代码了,这样就办理了简朴工厂模式的缺点。如下图所示。

工厂方法模式是简朴工厂模式的进一步抽象。由于使用了多态性,工厂方法模式保持了简朴工厂模式的优点,而且降服了它的缺点。
1.3.4 优缺点

优点:


  • 用户只必要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
  • 在系统增长新的产品时只必要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点:


  • 每增长一个产品就要增长一个具体产品类和一个对应的具体工厂类,这增长了系统的复杂度。
1.4 抽象工厂模式

前面先容的工厂方法模式中思量的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、传智播客只造就计算机软件专业的门生等。
这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只思量生产同等级的产品,但是在现实生活中很多工厂是综合型的工厂,能生产多等级(种类) 的产品,如电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
本节要先容的抽象工厂模式将思量多等级产品的生产,将同一个具体工厂所生产的位于差别等级的一组产品称为一个产品族,下图所示


  • 产品族:一个品牌下面的所有产品;比方华为下面的电脑、手机称为华为的产品族;
  • 产品等级:多个品牌下面的同种产品;比方华为和小米都有手机电脑为一个产品等级;

1.4.1 概念

是一种为访问类提供一个创建一组干系或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的差别等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂
1.4.2 结构

抽象工厂模式的主要角色如下:


  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个差别等级的产品。
  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,形貌了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。
1.4.3 实现

现咖啡店业务发生改变,不仅要生产咖啡还要生产甜点


  • 同一个产品等级(产品分类)

    • 咖啡:拿铁咖啡、美式咖啡
    • 甜点:提拉米苏、抹茶慕斯

  • 同一个风味,就是同一个产品族(相当于同一个品牌)

    • 美式风味:美式咖啡、抹茶慕斯
    • 意大利风味:拿铁咖啡、提拉米苏‘

要是按照工厂方法模式,必要定义提拉米苏类、抹茶慕斯类、提拉米苏工厂、抹茶慕斯工厂、甜点工厂类,很容易发生类爆炸情况。
所以这个案例可以使用抽象工厂模式实现。类图如下:

实现关系使用带空心三角箭头的虚线来表现
整体调用思绪:

1.4.4 优缺点

优点:
当一个产品族中的多个对象被设计成一起工作时,它能包管客户端始终只使用同一个产品族中的对象。
缺点:
当产品族中必要增长一个新的产品时,所有的工厂类都必要进行修改。
1.4.5 使用场景



  • 当必要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜好穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口雷同,客户端不依赖产品实例的创建细节和内部结构。
    如:输入法换皮肤,一整套一起换。天生差别操纵系统的程序。
总结(工厂都是为相识耦)


  • 简朴工厂

    • 所有的产品都共有一个工厂,假如新增产品,则必要修改代码,违背开闭原则·是一种编程风俗,可以鉴戒这种编程思绪

  • 工厂方法模式

    • 给每个产品都提供了一个工厂,让工厂专门负责对应的产品的生产,遵循开闭原则
    • 项目中用的最多

  • 抽象工厂方法模式

    • 假如有多个纬度的产品必要共同生产时,优先发起采用抽象工厂(工厂的工厂)
    • 一般的企业开辟中的较少

2. 策略模式

2.1 概述

先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。

定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互更换,且算法的变化不会影响使用算法的客户。策略模式属于对象举动模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给差别的对象对这些算法进行管理。



2.2 结构

策略模式的主要角色如下:


  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或举动。
  • 情况(Context)类:持有一个策略类的引用,最终给客户端调用。
优缺点

优点:


  • 策略类之间可以自由切换(好比上面把new Aircraft()直接换成new Car())
  • 易于扩展
  • 避免使用多重条件选择语句(ifelse),充实表现面向对象设计头脑。
缺点:


  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类
实战

详情参考链接
3.责任链模式

详情参考链接
面试文稿

简历上:专业技能:可以灵活运用设计模式,如工厂、策略、责任链设计模式,进行项目开辟。
面试官:你说说你相识的设计模式。
候选人:工厂设计模式包括:


  • 简朴工厂模式:它并不是一种设计模式,反而比力像是一种编程风俗。由一个工厂类根据传入参数创建具体产品对象,工厂逻辑集中在一个类中。
  • 工厂方法模式:为每种产品提供一个具体的工厂类,通过工厂接口来决定实例化哪种产品,解耦了工厂和产品的具体实现。
  • 抽象工厂模式:提供一个创建一组干系或互相依赖对象的接口,而无需指定它们的具体类,支持产品族的扩展和变化。
策略模式就是定义一系列算法,把它们一个个封装起来,并使它们可以互换。好比登陆时可以选择QQ大概微信登录。
责任链模式就是为了避免哀求发送者与多个哀求处理惩罚者耦合在一起,将所有哀求的处理惩罚者通过前一对象记着其下一个对象的引用而连成一条链;当有哀求发生时,可将哀求沿着这条链传递,直到有对象处理惩罚它为止。比力常见的springmvc中的拦截器,web开辟中的filter过滤器。
文稿例子,请转化为自己的话表述

以下是使用 Java 实现 简朴工厂模式工厂方法模式抽象工厂模式 的示例:

1. 简朴工厂模式

通过一个工厂类,根据类型创建具体的产品。
  1. // 产品接口
  2. interface Product {
  3.     void operation();
  4. }
  5. // 具体产品A
  6. class ProductA implements Product {
  7.     @Override
  8.     public void operation() {
  9.         System.out.println("Product A operation");
  10.     }
  11. }
  12. // 具体产品B
  13. class ProductB implements Product {
  14.     @Override
  15.     public void operation() {
  16.         System.out.println("Product B operation");
  17.     }
  18. }
  19. // 简单工厂
  20. class SimpleFactory {
  21.     public static Product createProduct(String type) {
  22.         switch (type) {
  23.             case "A":
  24.                 return new ProductA();
  25.             case "B":
  26.                 return new ProductB();
  27.             default:
  28.                 throw new IllegalArgumentException("Unknown product type");
  29.         }
  30.     }
  31. }
  32. // 使用示例
  33. public class SimpleFactoryDemo {
  34.     public static void main(String[] args) {
  35.         Product product = SimpleFactory.createProduct("A");
  36.         product.operation(); // 输出: Product A operation
  37.     }
  38. }
复制代码

2. 工厂方法模式

每种产品有自己的工厂类,新增产品时扩展工厂即可。
  1. // 产品接口
  2. interface Product {
  3.     void operation();
  4. }
  5. // 具体产品A
  6. class ProductA implements Product {
  7.     @Override
  8.     public void operation() {
  9.         System.out.println("Product A operation");
  10.     }
  11. }
  12. // 具体产品B
  13. class ProductB implements Product {
  14.     @Override
  15.     public void operation() {
  16.         System.out.println("Product B operation");
  17.     }
  18. }
  19. // 工厂接口
  20. interface Factory {
  21.     Product createProduct();
  22. }
  23. // 工厂A
  24. class FactoryA implements Factory {
  25.     @Override
  26.     public Product createProduct() {
  27.         return new ProductA();
  28.     }
  29. }
  30. // 工厂B
  31. class FactoryB implements Factory {
  32.     @Override
  33.     public Product createProduct() {
  34.         return new ProductB();
  35.     }
  36. }
  37. // 使用示例
  38. public class FactoryMethodDemo {
  39.     public static void main(String[] args) {
  40.         Factory factory = new FactoryA();
  41.         Product product = factory.createProduct();
  42.         product.operation(); // 输出: Product A operation
  43.     }
  44. }
复制代码

3. 抽象工厂模式

用于创建一组干系产品。
  1. // 产品接口
  2. interface ProductX {
  3.     void operationX();
  4. }
  5. interface ProductY {
  6.     void operationY();
  7. }
  8. // 具体产品X1
  9. class ProductX1 implements ProductX {
  10.     @Override
  11.     public void operationX() {
  12.         System.out.println("Product X1 operation");
  13.     }
  14. }
  15. // 具体产品X2
  16. class ProductX2 implements ProductX {
  17.     @Override
  18.     public void operationX() {
  19.         System.out.println("Product X2 operation");
  20.     }
  21. }
  22. // 具体产品Y1
  23. class ProductY1 implements ProductY {
  24.     @Override
  25.     public void operationY() {
  26.         System.out.println("Product Y1 operation");
  27.     }
  28. }
  29. // 具体产品Y2
  30. class ProductY2 implements ProductY {
  31.     @Override
  32.     public void operationY() {
  33.         System.out.println("Product Y2 operation");
  34.     }
  35. }
  36. // 抽象工厂
  37. interface AbstractFactory {
  38.     ProductX createProductX();
  39.     ProductY createProductY();
  40. }
  41. // 具体工厂1
  42. class Factory1 implements AbstractFactory {
  43.     @Override
  44.     public ProductX createProductX() {
  45.         return new ProductX1();
  46.     }
  47.     @Override
  48.     public ProductY createProductY() {
  49.         return new ProductY1();
  50.     }
  51. }
  52. // 具体工厂2
  53. class Factory2 implements AbstractFactory {
  54.     @Override
  55.     public ProductX createProductX() {
  56.         return new ProductX2();
  57.     }
  58.     @Override
  59.     public ProductY createProductY() {
  60.         return new ProductY2();
  61.     }
  62. }
  63. // 使用示例
  64. public class AbstractFactoryDemo {
  65.     public static void main(String[] args) {
  66.         AbstractFactory factory = new Factory1();
  67.         ProductX productX = factory.createProductX();
  68.         ProductY productY = factory.createProductY();
  69.         
  70.         productX.operationX(); // 输出: Product X1 operation
  71.         productY.operationY(); // 输出: Product Y1 operation
  72.     }
  73. }
复制代码

总结


  • 简朴工厂:通过单个工厂类,根据类型或参数创建产品实例。
  • 工厂方法:通过多个具体工厂类,专门创建对应的产品。
  • 抽象工厂:支持创建一组干系产品(如产品家属)。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表