工厂模式-依赖倒置原则

老板:阿飞啊,我们公司最近接了个项目,你看着设计一下,我给你说下需求。
项目组长阿飞:好啊,什么需求?
老板:我们找了一个合作的商铺,他们要设计一套面包销售系统。主要功能,根据用户选择的面包种类来下订单,面包目前有奶油口味面包和苹果口味面包,所有面包的制作流程都是---搅拌,搓圆,加工,烘烤。
项目组长阿飞:好的,我去想想怎么设计。
项目组长阿飞:小三啊,我给你个任务,…………,听懂了吗?
阿三:听懂了,飞哥。
项目组长阿飞:嗯嗯,好的,这个任务就交给你了,我要去处理点事情,我相信你。
阿三:。。。
三天过后。
阿三:飞哥,设计好了,你看下。

 1 package com.factoryPattern.factory;
 2
 3 /**
 4  * @program: designPattern
 5  * @description: 面包口味的抽象类
 6  * @author: Mr.Yang
 7  * @create: 2018-11-18 19:24
 8  **/
 9 public abstract class BreadFactory {
10     protected String name;
11     protected String type;
12
13     public BreadFactory stir(){
14         System.out.println("搅拌");
15         return this;
16     }
17
18     public BreadFactory rubbingRound(){
19         System.out.println("搓圆");
20         return this;
21     }
22
23     public BreadFactory machining(){
24         System.out.println("加工");
25         return this;
26     }
27     public BreadFactory bake(){
28         System.out.println("烘烤");
29         return this;
30     }
31
32     public String getName() {
33         return name;
34     }
35
36     public BreadFactory setName(String name) {
37         this.name = name;
38         return this;
39     }
40
41     public String getType() {
42         return type;
43     }
44
45     public BreadFactory setType(String type) {
46         this.type = type;
47         return this;
48     }
49 }

 

现在已有的两种口味继承这个抽象类--奶油面包

 package com.factoryPattern.breadKind;

 import com.factoryPattern.breadKind.factory.BreadFactory;

 /**
  * @program: designPattern
  * @description: 奶油味面包
  * @author: Mr.Yang
  * @create:
 **/
public class CreamBread extends BreadFactory {
    public CreamBread(){
        name="奶油味";
        type="2";
    }
    //可以重写父类方法,进行特殊处理
}

 

苹果味面包

 1  package com.factoryPattern.breadKind;
 2
 3  import com.factoryPattern.breadKind.factory.BreadFactory;
 4
 5  /**
 6   * @program: designPattern
 7   * @description: 苹果味面包
 8   * @author: Mr.Yang
 9   * @create:
10  **/
11 public class AppleBread extends BreadFactory {
12     public AppleBread(){
13         name="苹果味";
14         type="1";
15     }
16     //可以重写父类方法,进行特殊处理
17 }

 

然后是销售系统

 1  package com.factoryPattern.breadKind.breadOrder;
 2
 3  import com.factoryPattern.breadKind.AppleBread;
 4  import com.factoryPattern.breadKind.CreamBread;
 5  import com.factoryPattern.breadKind.factory.BreadFactory;
 6
 7  /**
 8   * @program: designPattern
 9   * @description: 面包订单销售类
10  * @author: Mr.Yang
11  * @create:
12  **/
13 public class BreadOrder {
14
15
16     BreadFactory orderBread(String type){
17         BreadFactory breadFactory;
18         if("cream".equalsIgnoreCase(type)){
19             System.out.println("创建奶油口味面包");
20             breadFactory=new CreamBread();
21         }else if("apple".equalsIgnoreCase(type)){
22             System.out.println("创建苹果口味面包");
23             breadFactory=new AppleBread();
24         }else{
25             System.out.println("无法确认的面包类型");
26             return null;
27         }
28
29         return breadFactory.stir()
30                 .rubbingRound()
31                 .machining()
32                 .bake();
33     }
34 }

 

项目组长阿飞:三啊,不错,学会使用抽象了,但是如果我还要增加好几种面包类型呢?阿尔法面包销售不好,不想做这个了呢?之前给你说过设计模式的原则之一,对拓展开放,对修改关闭。如果有改动,可能会一直在这个代码的基础上累加做修改的。最好把创建对象的代码与销售的代码分隔开。 
阿三:好的,我再修改修改(真的是,搞这么麻烦干嘛!)
又三天过后。
阿三:飞哥,修改好了,你看下。

新增了一个工程类

 1  package com.factoryPattern.breadCreate;
 2
 3  import com.factoryPattern.breadKind.AppleBread;
 4  import com.factoryPattern.breadKind.CreamBread;
 5  import com.factoryPattern.breadKind.factory.BreadFactory;
 6
 7  /**
 8   * @program: designPattern
 9   * @description: 面包创建工程
10  * @author: Mr.Yang
11  * @create:
12  **/
13 public class BreadCreateFactory {
14     public BreadFactory createBread(String type){
15         BreadFactory breadFactory=null;
16         if("cream".equalsIgnoreCase(type)){
17             System.out.println("创建奶油口味面包");
18             breadFactory=new CreamBread();
19         }else if("apple".equalsIgnoreCase(type)){
20             System.out.println("创建苹果口味面包");
21             breadFactory=new AppleBread();
22         }else{
23             System.out.println("无法确认的面包类型");
24             return null;
25         }
26         return breadFactory;
27     }
28 }

修改了销售类

 1  package com.factoryPattern.breadKind.breadOrder;
 2
 3  import com.factoryPattern.breadCreate.BreadCreateFactory;
 4  import com.factoryPattern.breadKind.factory.BreadFactory;
 5
 6  /**
 7   * @program: designPattern
 8   * @description: 面包订单销售类
 9   * @author: Mr.Yang
10  * @create:
11  **/
12 public class BreadOrder {
13     BreadCreateFactory breadCreateFactory;
14
15     public BreadOrder(BreadCreateFactory breadCreateFactory) {
16         this.breadCreateFactory = breadCreateFactory;
17     }
18
19     BreadFactory orderBread(String type) {
20         return breadCreateFactory.createBread(type)
21                 .stir()
22                 .rubbingRound()
23                 .machining()
24                 .bake();
25     }
26 }

 

项目组长阿飞:不错,这是一个简单工厂,但是你要记住,这并不是一个设计模式,而是一个编程习惯,一个不错的编程习惯,简单工厂把全部的事情,在一个地方处理完了,工厂方法是创建一个框架,让子类决定如何实现。还有领导说需求变了,这个面包店开了分店,一个在泰国,一个在新加坡,你看着再修改下吧,你可以考虑加入工厂方法。 
阿三:好的(我服了,真的是****)
又三天过后。
阿三:飞哥,修改好了,这是完整代码,你看下。
先是一个面包商店抽象类

 1  package com.factoryPattern.breadStore;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4
 5  /**
 6   * @program: designPattern
 7   * @description: 面包商店抽象类
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public abstract class BreadStoreFactory {
12
13     public BreadFactory orderBread(String type) {
14         return createBread(type)
15                 .stir()
16                 .rubbingRound()
17                 .machining()
18                 .bake();
19     }
20
21     abstract BreadFactory createBread(String type);
22 }

 

创建一个中国店铺子类实现商店抽象类

 1 package com.factoryPattern.breadStore;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4  import com.factoryPattern.kind.ChinaAppleBread;
 5  import com.factoryPattern.kind.ChinaCreamBread;
 6
 7  /**
 8   * @program: designPattern
 9   * @description: 中国店铺子类
10  * @author: Mr.Yang
11  * @create: -- :
12  **/
13 public class ChinaStore extends BreadStoreFactory{
14     @Override
15     BreadFactory createBread(String type) {
16         BreadFactory breadFactory=null;
17         if("cream".equalsIgnoreCase(type)){
18             System.out.println("创建中国奶油口味面包");
19             breadFactory=new ChinaCreamBread();
20         }else if("apple".equalsIgnoreCase(type)){
21             System.out.println("创建中国苹果口味面包");
22             breadFactory=new ChinaAppleBread();
23         }else{
24             System.out.println("无法确认的面包类型");
25             return null;
26         }
27         return breadFactory;
28     }
29 }

 

创建一个新加坡店铺子类

 1 package com.factoryPattern.breadStore;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4  import com.factoryPattern.kind.SingaporeAppleBread;
 5  import com.factoryPattern.kind.SingaporeCreamBread;
 6
 7  /**
 8   * @program: designPattern
 9   * @description: 新加坡店铺子类
10  * @author: Mr.Yang
11  * @create: -- :
12  **/
13 public class SingaporeStore extends BreadStoreFactory {
14     @Override
15     BreadFactory createBread(String type) {
16         BreadFactory breadFactory=null;
17         if("cream".equalsIgnoreCase(type)){
18             System.out.println("创建新加坡奶油口味面包");
19             breadFactory=new SingaporeCreamBread();
20         }else if("apple".equalsIgnoreCase(type)){
21             System.out.println("创建新加坡苹果口味面包");
22             breadFactory=new SingaporeAppleBread();
23         }else{
24             System.out.println("无法确认的面包类型");
25             return null;
26         }
27         return breadFactory;
28     }
29 }

 

创建一个泰国店铺子类

 1  package com.factoryPattern.breadStore;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4  import com.factoryPattern.kind.ThailandAppleBread;
 5
 6  /**
 7   * @program: designPattern
 8   * @description: 泰国店铺子类
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class ThailandStore extends BreadStoreFactory {
13     @Override
14     BreadFactory createBread(String type) {
15         BreadFactory breadFactory=null;
16         if("cream".equalsIgnoreCase(type)){
17             System.out.println("创建泰国奶油口味面包");
18             breadFactory=new ThailandAppleBread();
19         }else if("apple".equalsIgnoreCase(type)){
20             System.out.println("创建泰国苹果口味面包");
21             breadFactory=new ThailandAppleBread();
22         }else{
23             System.out.println("无法确认的面包类型");
24             return null;
25         }
26         return breadFactory;
27     }
28 }

 

面包口味的抽象类

 1  package com.factoryPattern.factory;
 2
 3  /**
 4   * @program: designPattern
 5   * @description: 面包口味的抽象类
 6   * @author: Mr.Yang
 7   * @create: -- :
 8   **/
 9  public abstract class BreadFactory {
10     protected String name;
11     protected String type;
12
13     public BreadFactory stir(){
14         System.out.println("搅拌");
15         return this;
16     }
17
18     public BreadFactory rubbingRound(){
19         System.out.println("搓圆");
20         return this;
21     }
22
23     public BreadFactory machining(){
24         System.out.println("加工");
25         return this;
26     }
27     public BreadFactory bake(){
28         System.out.println("烘烤");
29         return this;
30     }
31
32     public String getName() {
33         return name;
34     }
35
36     public BreadFactory setName(String name) {
37         this.name = name;
38         return this;
39     }
40
41     public String getType() {
42         return type;
43     }
44
45     public BreadFactory setType(String type) {
46         this.type = type;
47         return this;
48     }
49 }

 

中国苹果口味面包

 1  package com.factoryPattern.kind;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4
 5  /**
 6   * @program: designPattern
 7   * @description: 中国苹果口味面包
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public class ChinaAppleBread  extends BreadFactory {
12     public ChinaAppleBread(){
13         name="中国苹果口味";
14         type="";
15     }
16     //可以重写父类方法,进行特殊处理
17 }

 

中国奶油口味面包

 1  package com.factoryPattern.kind;
 2
 3  import com.factoryPattern.factory.BreadFactory;
 4
 5  /**
 6   * @program: designPattern
 7   * @description: 中国奶油口味面包
 8   * @author: Mr.Yang
 9   * @create: -- :
10  **/
11 public class ChinaCreamBread extends BreadFactory {
12     public ChinaCreamBread(){
13         name="中国奶油口味";
14         type="";
15     }
16     //可以重写父类方法,进行特殊处理

 

还有新加坡苹果口味面包,新加坡奶油口味面包,泰国苹果口味面包,泰国奶油口味面包

测试类

 1  package com.factoryPattern.patternTest;
 2
 3  import com.factoryPattern.breadStore.BreadStoreFactory;
 4  import com.factoryPattern.breadStore.ChinaStore;
 5
 6  /**
 7   * @program: designPattern
 8   * @description: 测试类
 9   * @author: Mr.Yang
10  * @create: -- :
11  **/
12 public class Test {
13     public static void main(String[] args) {
14         System.out.println("中国顾客买苹果味道面包");
15         BreadStoreFactory chinaBreadStoreFactory = new ChinaStore();
16         chinaBreadStoreFactory.orderBread("apple");
17     }
18 }

 

测试结果

1 中国顾客买苹果味道面包
2 创建中国苹果口味面包
3 搅拌
4 搓圆
5 加工
6 烘烤
 

项目组长阿飞:看着不错,给我讲解一下吧。
阿三:我所用的是设计模式中的工厂模式,让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。我简单的画了个图

阿三:大致如图,工程模式的定义:定义了一个创建对象的接口,但有子类决定要实例化的类是哪一个。工程方法让类把实例化推迟到子类

项目组长阿飞:很好,看来你已经掌握了工程模式的精髓,工程模式遵循了一个设计原则:“要依赖抽象,不要依赖具体实现。”,它有一个响亮的名字:“依赖倒置原则”。 你看你这两个图。创建者抽象BreadStoreFactory依赖与BreadFactory抽象类,面包的具体实现(chinaAppleBread,chinaCreamBread)依赖与BreadFactory抽象类,想要遵循依赖倒置原则,工程方法并非是唯一的,但是确是最有威力的技巧之一。

阿三:好的(我早就知道了---膨胀的一批)

原文地址:https://www.cnblogs.com/yangxiaojie/p/10010284.html

时间: 2024-10-14 19:57:18

工厂模式-依赖倒置原则的相关文章

敏捷软件开发:原则、模式与实践——第11章 DIP:依赖倒置原则

第11章 DIP:依赖倒置原则 DIP:依赖倒置原则: a.高层模块不应该依赖于低层模块.二者都应该依赖于抽象. b.抽象不应该依赖于细节.细节应该依赖于抽象. 11.1 层次化 下图展示了一个简单的层次化方案: 高层的Policy层使用了低层的Mechanism层,而Mechanism层又使用了更细节的Utility层.它存在一个隐伏的错误特征,那就是:Policy层对于其下一直到Utility层的改动都是敏感的.依赖关系是传递的. 下图展示了一个更为合适的模型: 每个较高层次都为它所需要的服

C#软件设计——小话设计模式原则之:依赖倒置原则DIP

前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”,即各方便都有战斗力.关于设计模式,作为程序猿的我们肯定都不陌生.博主的理解,所谓设计模式就是前人总结下来的一些对于某些特定使用场景非常适用的优秀的设计思路,“前人栽树,后人乘凉”,作为后来者的我们就有福了,当我们遇到类似的应用场景的时候就可以直接使用了.关于设计模式的原则,博主将会在接下来的几篇里面

增删改查也有设计模式——依赖倒置原则另解

一个增删改查的例子解读面向接口编程和依赖倒置原则 依赖倒置原则介绍 依赖倒置原则包括两个部分 .高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象. 抽象不应该依赖于具体实现,具体实现应该依赖于抽象. 例子 现在有如下场景和需求:老板要求设计任务模块,包括发布任务和撤回任务等.假设这个需求只给了几个小时去做,那肯定是来不及设计了,写到哪算哪.定义撤回接口的控制层如下 @RequestMapping('cancel') @ResponseBody public String cancelT

C#编程:依赖倒置原则DIP

一.前言 我们先来看看传统的三层架构,如下图所示: 从上图中我们可以看到:在传统的三层架构中,层与层之间是相互依赖的,UI层依赖于BLL层,BLL层依赖于DAL层.分层的目的是为了实现“高内聚.低耦合”.传统的三层架构只有高内聚没有低耦合,层与层之间是一种强依赖的关系,这也是传统三层架构的一种缺点.这种自上而下的依赖关系会导致级联修改,如果低层发生变化,可能上面所有的层都需要去修改,而且这种传统的三层架构也很难实现团队的协同开发,因为上层功能取决于下层功能的实现,下面功能如果没有开发完成,则上层

设计模式六大原则(3)--依赖倒置原则

定义: 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口:抽象接口不应该依赖于具体实现.而具体实现则应该依赖于抽象接口.依赖倒置原则英文全称为Dependence Inversion Principle,简称为DIP. 问题由来: 类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案: 将类A修改为依赖接口I,类B和

设计模式六大原则(3):依赖倒置原则

依赖倒置原则 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒转原则(Dependency

设计模式 之 设计的 六大原则(3) 依赖倒置原则

依赖倒置原则 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则基于这样一个事实:相对于

设计模式六大原则(3):依赖倒置原则(转载)

设计模式六大原则(3):依赖倒置原则 定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则

设计模式六大原则之三:依赖倒置原则

定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象:抽象不应该依赖细节:细节应该依赖抽象. 问题由来:类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成.这种场景下,类A一般是高层模块,负责复杂的业务逻辑:类B和类C是低层模块,负责基本的原子操作:假如修改类A,会给程序带来不必要的风险. 解决方案:将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率. 依赖倒置原则基于这样一个事实:相对于细节的多变性,