前言
这是一篇使用教程式语言写的技术笔记,浅谈了我对面向对象思想以及设计模式的一些认识与理解。
有别于网上大神们技术文章,我使用较为通俗与平易近人的例子阐述这些知识。也希望感兴趣的童鞋们能收获一些知识。
示例代码使用java写的。如果疏误,欢迎指正。
1、抽象
众所周知,面向对象的最核心部分就是抽象。
抽象,即抽取其本象。是人类观察事物,并提取其本质特征或共同点的一种智慧。
而面向对象的设计哲学就是依赖抽象,而不是依赖具体。因为大千世界事物是千变万化的,但俗话说的好,万变却不离其宗。事物的本质(抽象)往往是非常稳定的。
着眼于软件工程,需求的千变万化是导致软件危机的罪魁祸首,因此一个好的设计就是要以不变应万变。这就是面向对象的初衷。具体而言,对于事物的本质,我们可抽象出其接口(interface )。现在比较热门的接口驱动编程,便是由此而来。因为依赖抽象,可以使客户代码相对稳定和健壮。可以使具体实现的变动,在一定程度上较少的影响客户代码。
举个例子吧。苹果 橘子 梨 这些有什么共同点?他们是可以吃的eatable(我们只分析行为上的本质,这是由这些事物的目的性所决定的)
class Apple{
public void eat(){
System.out.println("delicious apple!");
}
}
class Orange{
public void eat(){
System.out.println("delicious orange");
}
}
如果我们依赖具体 那么是什么情况呢
class Child{
public void wantToEat(){
Apple apple=new Apple();
apple.eat();
}
}
这时候不想吃苹果了想吃橘子 怎么办 那我们只好修改代码
class Child{
public void wantToEat(){
Orange orange=new Orange();
orange.eat();
}
}
你发现了什么,我们修改了所有的业务逻辑(客户)代码,这样带来的代价是巨大的。
因此,我们使用抽象将其本质抽取出来
interface Eatable{
public void eat();
}
class Apple implements Eatable{
//@重写
public void eat(){
System.out.println("delicious apple!");
}
}
class Orange implements Eatable{
//@重写
public void eat(){
System.out.println("delicious orange");
}
}
class Child{
public void wantToEat(){
Eatable eatble=new Apple();
eatble.eat();
}
}
这样一来,如果想换换口味,只需要修改实例化eatble的代码(new Apple())即可。因此显而易见,我们付出了较少的代价,来应对需求变更。(在这里看起来虽然很粗浅很不起眼,但在实际的工程里代价差距可能是惊人的)
2、工厂模式
然而,问题也来了。虽然我们依赖了抽象,但是抽象(eatable)与具体实现(apple)之间的关系(=new),也出现在我们的客户端代码里,这依旧是一种强耦合。这时候工厂模式出现了。
他使得产品的具体实现(生产)交给工厂处理,而业务逻辑(客户代码)只需要向工厂索要产品即可,他并不关心,工厂如何生产,并且生产什么。只要符合我们之前约定的产品本质即可。
对于,我们的例子,工厂就像一个冰箱。代码如下
interface Eatable{
public void eat();
}
class Apple implements Eatable{
//@重写
public void eat(){
System.out.println("delicious apple!");
}
}
class Orange implements Eatable{
//@重写
public void eat(){
System.out.println("delicious orange");
}
}
class Fridge{
//静态工厂
static public Eatable getEatable(string type){
if("fruit".equals(type)) return new Apple();
elseif("bread".equals(type)) return new Tiramisu();
}
}
class Child{
public void wantToEat(){
Eatable eatble=Fridge.getEatable("fruit");
eatble.eat();
}
}
写到这你们发现了什么,即使我想换口味,甚至不用修改一行客户代码!!只需要修改工厂代码就行了!!
当然了,这时候很多童鞋都会问了。你不还得修改代码么,你new不写在这儿不还得写在其他地儿么?哼 换汤不换药。
很好,这时需要请出我们的小皮鞭SOC了。
3、SOC
即Separation of concerns。关注点分离。是人类的一种解决问题的思维方法。先将复杂的问题做合理的分解,然后再分别仔细研究问题的不同侧面(关注点)。
SOC可以说是很多设计模式的原动力。【包括现在越来越响的AOP(Aspect Oriented Programming面向切面编程)当然此为后话】更有人说,架构就是关注点分离。
SOC带来的好处是使复杂的问题变得清晰,分而治之又为维护和扩展带了很大的便利。而且有点儿像四人帮的SRP(单一职责原则)但他不仅仅在责任上分离,还在视角上分离。
从最早的C语言 .c .h文件的分离,到后来的三层架构、MVC,乃至现在IOC AOP无不体现了这种分离。
嗯 回到我们的问题。虽然工厂并没有消除掉抽象与具体之间的联系,依然会存在new实例化。但是他将产品的生产和使用进行了分离。
然而这种分离却不是很彻底。因为客户代码中出现了工厂代码。我们依然要主动要求工厂去给我们建立依赖关系,虽然是间接依赖关系。
这时候,也该请出做了半天冷板凳的IOC了
4、IOC
全称是Inversion of Control,控制反转。或者称之为DI--Dependency Inversion 依赖倒置(其实更形象的说是依赖注入)。我们上面说了。 我依然是是主动去要求建立依赖的(体现在调用工厂创建实例)。
而IOC的原理是好莱坞法则:Don't call us, we'll call you(别来找我,我会去找你的!)
也就是说一个对象所依赖的对象,是有其他人主动交给你的。这个其他人是谁?没错就是容器
spring 就是这样的一个容器(容器即提供一系列服务的管理器,而spring就是提供依赖注入等服务的容器)。
回到咱们的例子就是。以前child是从冰箱里自己拿水果吃。而这个child是个娇生惯养的孩子,不想自己拿。
因此每次都是妈妈亲自交给他,他只专注吃这也动作。这也是最彻底的分离。
我们需要稍微修改下代码
将可吃的东西eatable作为child的成员变量(体现依赖)。
使用工厂模式
interface Eatable{
public void eat();
}
class Apple implements Eatable{
//@重写
public void eat(){
System.out.println("delicious apple!");
}
}
class Orange implements Eatable{
//@重写
public void eat(){
System.out.println("delicious orange");
}
}
class Fridge{
//静态工厂
static public Eatable getEatable(string type){
if("fruit".equals(type)) return new Apple();
elseif("bread".equals(type)) return new Tiramisu();
}
}
class Child{
private Eatble eatble;
public void wantToEat(){
Eatable eatble=Fridge.getEatable("fruit");
eatble.eat();
}
}
使用spring的IOC方法。
interface Eatable{
public void eat();
}
class Apple implements Eatable{
//@重写
public void eat(){
System.out.println("delicious apple!");
}
}
class Orange implements Eatable{
//@重写
public void eat(){
System.out.println("delicious orange");
}
}
class Fridge{
//静态工厂
static public Eatable getEatable(string type){
if("fruit".equals(type)) return new Apple();
elseif("bread".equals(type)) return new Tiramisu();
}
}
class Child{
private Eateble eatble;
//构造注入
public Child(Eatable eatble){
this.eatble=eatble;
}
public void wantToEat(){
this.eatble.eat();
}
}
看到这,你应该已经发现了工厂模式与IOC的区别。客户代码中再也没了讨厌的new 和可恶的冰箱了。我只需要专注一件事,就是吃!(吃不死你)
而这个eatble是完全是由spring容器从Child构造函数中注入进来的。整个业务逻辑清晰明了,这就是传说中高内聚,低耦合啊!
当然,我们还是要付出一定的代价。要写一些注入代码(这里牵涉spring的语法细节 不再赘述)。
虽然如此,但这确实比较完美的做到关注点分离。同时也为实现AOP提供了技术基础。
分享到:
相关推荐
**工厂模式的IoC应用** 在软件工程中,控制反转(Inversion of Control,简称IoC)是一种设计原则,它将对象的创建和管理权从代码中剥离出来,交由一个外部容器负责。Spring框架是Java领域实现IoC的典型代表,通过...
在Spring中,工厂模式可以与IoC容器结合使用,例如在【springFactory】和【springFactoryJDOM】的示例中,我们可能会看到如何使用Spring的Bean工厂来创建和管理对象。Spring提供了XML配置和注解两种方式来声明和管理...
1. 利用注解、反射和工厂模式设计一个简单的IoC容器 2. 该IoC容器包含3个注解和一个IoC容器类(AnnotationConfigApplicationContext),其定义如下: 注解 含义 @Component 标注Bean @Autowired 标注需要被注入的...
在软件开发领域,IOC(Inversion of Control,控制反转)模式和工厂模式是两种常见的设计模式,它们在解决对象创建和依赖关系管理方面各有特点。本文主要探讨这两者之间的区别和联系。 首先,IOC模式的核心思想是将...
**Spring中的IoC与工厂模式对比** 虽然简单工厂模式在某些场景下能有效地创建对象,但它仍然存在一定的局限性,比如不易扩展、违反开闭原则等。Spring的IoC容器则提供了更高级别的抽象,能够管理多个对象及其依赖...
IOC(Inversion of Control,控制反转)模式是一种软件设计原则,它在面向对象编程中用于解耦组件之间的依赖关系。C#中实现IOC的一种常见方式是通过依赖注入(Dependency Injection,DI)。在这个“IOC模式 c#经典...
现在,我们来看IoCTest这个压缩包中的文件,虽然没有具体的内容,但我们可以假设这是一个简单的IoC示例。通常,这样的测试文件可能会包含以下内容: 1. 一个接口或抽象类,定义了需要被依赖的服务。 2. 一个或多个...
Java Spring代理模式AOP-IOC分析 一、代理模式概述 在软件设计中,代理模式是一种常用的设计模式。它可以在不修改原始代码的情况下,扩展或修改原始对象的行为。代理模式可以分为静态代理和动态代理两种。静态代理...
在本文中,我将深入探索这个模式的工作原理,给它一个更能描述其特点的名 字——“依赖注入”(Dependency Injection),并将其与“服务定位器”(Service Locator) 模式作一个比较。不过,这两者之间的差异并不太...
JAVA设计模式之IOC实战02
### IoC 容器与 Dependency Injection 模式详解 #### 一、IoC 容器的概念及重要性 IoC(Inversion of Control,控制反转)容器是现代软件开发中的一项关键技术,尤其在 Java 社区中备受关注。它允许程序员以一种...
Java简单工厂模式是一种设计模式,它是创建型模式的一种,用于将对象的创建过程封装到一个独立的工厂类中,使得客户端代码无需关心具体的对象创建细节,只需要知道如何调用工厂方法即可得到所需的对象。这种模式在...
关于`模拟Spring Bean工厂练习`,这可能是指通过编程方式模拟Spring框架中的Bean工厂,Spring框架使用IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)的概念,其中工厂模式是其核心。...
Spring IOC 04 配置通过静态工厂方法创建的bean、实例工厂创建的bean、FactoryBean (1)bean的创建默认就是框架利用反射new出来的bean实例; (2)工厂模式:工厂帮我们创建对象,有一个专门帮我们创建对象的类,这...
JAVA设计模式之IOC实战01
Spring 中 IoC 优点与缺点解析 IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 ...
这篇文章将深入探讨对象池工厂的概念、工作原理以及与IOC容器的关系。 首先,让我们理解什么是对象池。对象池是预先创建并存储一组对象的集合,当系统需要一个新对象时,不是直接创建,而是从池中获取已存在的对象...
在Spring框架中,依赖注入(Inversion of Control, IoC)和面向切面编程(Aspect Oriented Programming, AOP)是两大核心特性。本篇将深入探讨如何通过注解方式来模拟Spring的这两种机制,帮助你理解其底层原理。 #...