zoukankan      html  css  js  c++  java
  • 创建型-抽象工厂模式学习

    1、抽象工厂模式的意图;
      提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

    2、抽象工厂模式的适用性;

      抽象工厂模式中的工厂类中可声明多个工厂方法,其中,不同的工厂方法可以返回不同类别的产品,同一个工厂中可以创建多个不同种类的产品。

    • 一个系统要独立于它的产品的创建、组合和表示时。
    • 一个系统要由多个产品系列中的一个来配置时。
    • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
    • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

    3、场景描述;
      考虑一个生产多种不同风格的家具的工厂(FurnitureFactory),不同风格的家具系列可以提供不同的门、窗、地板等的组合,为同一所住房可以提供不同的外观和行为。

    4、抽象工厂模式类图;

        

    角色

    • AbstractFactory:提供给用户类Client使用工厂创建对象的接口;
    • Client:用户类;
    • ConcreteFactory1、ConcreteFactory2:AbstractFactory类的具体实现类,包含了创建具体对象的方法;封装了不同的具体产品作为一个系列(如ProductA1、ProductB1、ProductC1);
    • ProductA1、ProductA2:一般具有相同的父类ProductA,但是ProductA1、ProductA2提供了不同的展现形式;

    协作

    • 用户类(Client)对象使用具体工厂实例(ConcreteFactory1、ConcreteFactory2),调用抽象工厂提供的接口(即AbstractFactory中创建产品ProductA、ProductB、ProductC的方法)来创建对应的产品。如,通过ConcreteFactory1可以生产ProductA1、ProductB1、ProductC1等。
    • 用户类在使用时,通过创建具体工厂实例,来创建由该工厂类生产的同一系列的产品。

    5、代码实现;

      5.1 工程结构图;

      

    5.1.2实例类图;

        

    实例类图中的类基本对应设计模式的一般化类图。
    其中FurnitureFactory是接口,ExpensiveDoor是Door的子类,ExpensiveFloor是Floor的子类,ExpensiveWindow是Window的子类。

    5.2实践;
    5.2.1 基本组件类;
    Window.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class Window {
    4     public Window(){
    5         System.out.println("I'm a ordinary window");
    6     }
    7 }

    Floor.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class Floor {
    4     public Floor(){
    5         System.out.println("I'm a ordinary floor.");
    6     }
    7 }

    Door.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class Door {
    4     public Door(){
    5         System.out.println("I'm a ordinary door.");
    6     }
    7 }

    ExpensiveWindow.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class ExpensiveWindow extends Window {
    4     public ExpensiveWindow(){
    5         System.out.println("I'm a expensive window.");
    6     }
    7 }

    ExpensiveFloor.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class ExpensiveFloor extends Floor {
    4     public ExpensiveFloor(){
    5         System.out.println("I'm a expensive floor");
    6     }
    7 }

    ExpensiveDoor.java

    1 package com.crazysnail.furnitures;
    2 
    3 public class ExpensiveDoor extends Door{
    4     public ExpensiveDoor(){
    5         System.out.println("I'm a expensive door.");
    6     }
    7 }

    5.2.2工厂类;
    FurnitureFactory.java

    1 package com.crazysnail.abstractfactory;
    2 
    3 //抽象工厂模式中对外开放的接口,接口中定义了抽象工厂能够生产的产品种类
    4 public interface FurnitureFactory{
    5     public Window createWindow();
    6     public Floor createFloor();
    7     public Door createDoor();
    8 }

    OrdinaryFurnitureFactory.java 

     1 package com.crazysnail.abstractfactory;
     2 
     3 //普通家具的工厂类,组合了普通的Window、Floor、Door类作为一个系列来使用
     4 public class OrdinaryFurnitureFactory implements FurnitureFactory {
     5     @Override
     6     public Window createWindow() {
     7         return new Window();
     8     }
     9     @Override
    10     public Floor createFloor() {
    11         return new Floor();
    12     }
    13     @Override
    14     public Door createDoor() {
    15         return new Door();
    16     }
    17 }

    ExpensiveFurnitureFactory.java 

     1 package com.crazysnail.abstractfactory;
     2 
     3 //昂贵家具工厂类,组合了昂贵的ExpensiveWindow、ExpensiveFloor、ExpensiveDoor类,作为一个系列来使用
     4 public class ExpensiveFurnitureFactory implements FurnitureFactory {
     5     @Override
     6     public Window createWindow() {
     7         return new ExpensiveWindow();
     8     }
     9     @Override
    10     public Floor createFloor() {
    11         return new ExpensiveFloor();
    12     }
    13     @Override
    14     public Door createDoor() {
    15         return new ExpensiveDoor();
    16     }
    17 }

    5.2.3 使用抽象工厂举例;
    DecoretionCompany.java

     1 package com.crazysnail.abstractfactory;
     2 
     3 /**
     4  * 
     5  * 
     6  * 易于交换产品系列
     7  * 有利于控制产品的一致性,控制使用相同系列的门、窗、地板
     8  * 提供给用户的都是一些系列化的产品
     9  * 
    10  * But,难以支持新种类的产品;
    11  * 
    12  * 提供给用户的接口仅仅是不同的家具工厂,但是用户并不知晓具体的类
    13  *
    14  */
    15 public class DecorationCompany {
    16     public void decorateHouse(FurnitureFactory factory, House house){
    17         Window window = factory.createWindow();
    18         Door door = factory.createDoor();
    19         Floor floor = factory.createFloor();
    20         
    21         /*装饰*/
    22         house.addWindow(window);
    23         house.addDoor(door);
    24         house.addFloor(floor);
    25     }
    26 }

    6、总结;
      6.1 抽象工厂的优点;

    • 分离了具体的类——提供给用户类的接口仅仅是抽象工厂类及其子类,隐藏了组件类的具体实现。
    • 使得易于交换产品系列——在用户类中使用时,可以很方便的替换产品的系列,如只要DecorationCompany类中的decorateHouse方法中factory参数,便可以替换整个样式。
    • 有利于产品的一致性——将一组不同的组件组成一个系列来使用,如例子中的将Window、Door、Floor封装到OrdinaryFurnitureFactory中作为一个系列使用,将ExpensiveWindow、ExpensiveDoor、ExpensiveFloor封装到ExpensiveFurnitureFactory中来作为一个系列来使用。

      6.2 抽象工厂的缺点;

    • 难以支持新种类的产品——若要能够生产新的产品,则需要同时修改抽象工厂类及其子类。

     7、抽象工厂模式VS工厂方法

      工厂方法模式中的工厂仅用于生产一种类型的产品;抽象工厂模式中的工厂用于生产多种类型的产品,并将不同类型的产品封装为一个产品族。

  • 相关阅读:
    Clean Code读书笔记
    Junit 断言 assertThat Hamcrest匹配器
    SpringMVC 常用注解
    SpringMVC 流程 配置 接口
    ng-select ng-options ng-repeat的用法与区别
    javascript总结
    intellij安装 配置 创建项目
    git常用操作指令
    springmvc报错 org.springframework.web.servlet.DispatcherServlet
    linux笔记:RPM软件包管理-源码包管理
  • 原文地址:https://www.cnblogs.com/-crazysnail/p/3923161.html
Copyright © 2011-2022 走看看