锁定老帖子 主题:阿Q:革命了,革命了!(也谈IOC的好处)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-03-18
引用 存在变化时抽象变化为接口,然后注入接口以适应变化
引用 至少在struts里面在action里直接new 一个facade 或者bo很正常不需要再注射进去什么没有必要
说的有道理,不过new facade和bo不是一个好注意. 真要使用另一个实现,怕要改动代码无数,mock test也不可能了。 |
|
返回顶楼 | |
发表时间:2005-03-18
frankensteinlin 写道 引用 很简单的一个例子:原本这个facade是在本地实现的,回头我说了,不要在本地实现,远端有个web service实现版本,你改用那个。那么好了,你是不是要改代码? 这个搞大了,我经验不够,还没有碰到过这种情况!没话说了,我想这个估计在设计前就会想到的吧,否则可行性分析做的好像不够啊 要是什么都能预先想到,那就不用设计了,吭哧吭哧把代码堆出来就完事。现在CSDN的技术部门就经常遇到这种事情,任何一个功能都有可能某一天变成一个web service,你要预先想到是不可能的。 J2EE世界还有个例子。一个application原本是co-locate的,突然某一天变成distribute的,那么好了,很多资源对象(比如DataSource)就不能从本地创建,必须到JNDI去拿。同样的道理,如果不是依赖注射得到这些对象,你是不是又得改代码了? |
|
返回顶楼 | |
发表时间:2005-03-18
ioc是违反OO封装原则的典型,将一个对象的内部构造暴露给外部并将该对象的建造推委给外部是危险及不负责任的。
举一个浅显易懂的例子,我们以PC这个对象为例。 任何一台PC都是由CPU、内存等标准部件构成,为了方便讨论,我们将部件简化为CPU及内存。 class CPU; class Memory; class PC { CPU m_cpu; Memory m_memory; } 对于end user来说,他只需要知道如何使用PC这个对象,根本就不需要了解PC的内部结构,更不要说自己去装配一台PC。但是作为供应商,我们当然会按照客户的需求提供不同档次的PC,分为高、中、低三个档次,同理,CPU和Memory也分为高、中、低三个档次。 那么对于客户所需要的PC,应该由谁来装配呢?在现实中,当然是由工厂或者某个生产部门来组装PC,直接把这种概念搬过来好象很自然。但是,OO世界是一个高度抽象的世界,抽象世界有自己的运行规则,将现实中的现象直接搬过来是无法发挥OO的优势的。所以在OO设计中,我们可以让PC组装自己。 public class PC { protected CPU m_cpu; protected Memory m_memory; protected PC(); { ConstructMe();; } virtual protected void ConstructMe(); { m_cpu = new CPU();; m_memory = new Memory();; } } public class 高档PC : PC { public 高档PC(); { } protected override void ConstructMe(); { m_cpu = new 高速CPU();; m_memory = new 大容量Memory();; } } 对于end user而言,只有PC是可见的,档次也可以自由选择,而PC的内部结构也没有暴露的危险,任何一种档次的PC都对自己完全负责,产品线的概念也得到了完整体现。 封装、继承和多态完美的结合足以解决大部分问题,ioc是反OO的,因此根本不值得提倡,所谓框架解决的只是细枝末节的问题。 |
|
返回顶楼 | |
发表时间:2005-03-18
age0 写道 ioc是违反OO封装原则的典型,将一个对象的内部构造暴露给外部并将该对象的建造推委给外部是危险及不负责任的。
举一个浅显易懂的例子,我们以PC这个对象为例。 任何一台PC都是由CPU、内存等标准部件构成,为了方便讨论,我们将部件简化为CPU及内存。 class CPU; class Memory; class PC { CPU m_cpu; Memory m_memory; } 对于end user来说,他只需要知道如何使用PC这个对象,根本就不需要了解PC的内部结构,更不要说自己去装配一台PC。但是作为供应商,我们当然会按照客户的需求提供不同档次的PC,分为高、中、低三个档次,同理,CPU和Memory也分为高、中、低三个档次。 那么对于客户所需要的PC,应该由谁来装配呢?在现实中,当然是由工厂或者某个生产部门来组装PC,直接把这种概念搬过来好象很自然。但是,OO世界是一个高度抽象的世界,抽象世界有自己的运行规则,将现实中的现象直接搬过来是无法发挥OO的优势的。所以在OO设计中,我们可以让PC组装自己。 public class PC { protected CPU m_cpu; protected Memory m_memory; protected PC(); { ConstructMe();; } virtual protected void ConstructMe(); { m_cpu = new CPU();; m_memory = new Memory();; } } public class 高档PC : PC { public 高档PC(); { } protected override void ConstructMe(); { m_cpu = new 高速CPU();; m_memory = new 大容量Memory();; } } 对于end user而言,只有PC是可见的,档次也可以自由选择,而PC的内部结构也没有暴露的危险,任何一种档次的PC都对自己完全负责,产品线的概念也得到了完整的体现。 封装、继承和多态完美的结合足以解决大部分的问题,ioc是反OO的,因此根本不值得提倡的,所谓框架解决的只是细枝末节的问题。 侬这说的跟IoC有啥西关系?有什么CPU有什么内存,这是PC暴露给使用者的接口么?你们家的PC大概是整天畅着机箱盖让你在里头捣腾,我们家的可不是。这些都是实现,不是接口。IoC从来就是一个实现问题,我就不晓得它破坏谁的封装。 说得再细一点,“任何一种档次的PC都对自己完全负责,产品线的概念也得到了完整的体现”这话就叫扯淡。咱们先摆开软件不说,你随便去找任何一种制造业的老板,你问问他,他的一条“产品线”是不是只能生产一种档次的产品?所谓产品线,就是不管哪种零件只要符合规格拿过来都能往上插,插上都能用。所谓“高档PC”,其实只是一个标签,它可以是另贴上去的,也可以是根据里面的零件算出来的。把“高档PC”变成“PC”的一个子类,您是不是还打算把“银白色PC”也变成一个子类啊?“液晶屏PC”呢?这种明显的类爆炸都看不出来您还跟这白活什么OO呢。还是那句话,咱先把基础搞搞清楚,别瞪着俩大眼说瞎话,啊。 |
|
返回顶楼 | |
发表时间:2005-03-18
age0 写道 ioc是违反OO封装原则的典型,将一个对象的内部构造暴露给外部并将该对象的建造推委给外部是危险及不负责任的。
举一个浅显易懂的例子,我们以PC这个对象为例。 任何一台PC都是由CPU、内存等标准部件构成,为了方便讨论,我们将部件简化为CPU及内存。 class CPU; class Memory; class PC { CPU m_cpu; Memory m_memory; } 对于end user来说,他只需要知道如何使用PC这个对象,根本就不需要了解PC的内部结构,更不要说自己去装配一台PC。但是作为供应商,我们当然会按照客户的需求提供不同档次的PC,分为高、中、低三个档次,同理,CPU和Memory也分为高、中、低三个档次。 那么对于客户所需要的PC,应该由谁来装配呢?在现实中,当然是由工厂或者某个生产部门来组装PC,直接把这种概念搬过来好象很自然。但是,OO世界是一个高度抽象的世界,抽象世界有自己的运行规则,将现实中的现象直接搬过来是无法发挥OO的优势的。所以在OO设计中,我们可以让PC组装自己。 public class PC { protected PU m_cpu; protected Memory m_memory; protected PC(); { ConstructMe();; } virtual protected void ConstructMe(); { m_cpu = new CPU();; m_memory = new Memory();; } } public class 高档PC : PC { public 高档PC(); { } protected override void ConstructMe(); { m_cpu = new 高速CPU();; m_memory = new 大容量Memory();; } } 对于end user而言,只有PC是可见的,档次也可以自由选择,而PC的内部结构也没有暴露的危险,任何一种档次的PC都对自己完全负责,产品线的概念也得到了完整体现。 封装、继承和多态完美的结合足以解决大部分问题,ioc是反OO的,因此根本不值得提倡,所谓框架解决的只是细枝末节的问题。 这是用继承实现变化的典型例子,pc子类的多少完全取决于档次的多少,或者说取决于pc内可更换零件的组合的个数,这样可更换零件的种类增加时,子类将会成爆炸指数增加。 当然这也没什么不好,只要你不觉得繁琐,但我更倾向于用接口聚合的方式实现变化。 final class PC { CPU _cpu; Memory _memory; void setCPU(CPU cpu); { _cpu=cpu; } void setMemory(Memory memory); { _memory=memory; } } 这样不同档次的pc只需要更换不同的CPU或Memory就能获得。 |
|
返回顶楼 | |
发表时间:2005-03-18
[quote="frankensteinlin]要是什么都能预先想到,那就不用设计了,吭哧吭哧把代码堆出来就完事。现在CSDN的技术部门就经常遇到这种事情,任何一个功能都有可能某一天变成一个web service,你要预先想到是不可能的。
很简单啊,facade门面么,换个门面不久行了?,何必要让dipacch 来知道呢早就封装好了 这就是封装的好处啊,成天用web service 就现在的网络和硬件来说 不会是个好的设计 gigix 写道 [quote="frankensteinlin]J2EE世界还有个例子。一个application原本是co-locate的,突然某一天变成distribute的,那么好了,很多资源对象(比如DataSource)就不能从本地创建,必须到JNDI去拿。同样的道理,如果不是依赖注射得到这些对象,你是不是又得改代码了?
你就factory自己修改一下不久行了,指责不要太清楚哦!我才不管是远程的datasource还是本地的呢。 |
|
返回顶楼 | |
发表时间:2005-03-18
引用 ioc是违反OO封装原则的典型,将一个对象的内部构造暴露给外部并将该对象的建造推委给外部是危险及不负责任的 和我的想法一样。 A:我要买的是联想天翼电脑,能看碟片 上上网就行了?B:按照要求去找作。难道还要 B 自己部决定组件,还要问谁要?肯定是和A无关的! A{ new B(); b.do! } 不要告诉我 A{ B b set(B b) } 再让n Type 住射给A? A 连自己找到代理去买电脑的本事也没有,他还是个程序员么!it文盲阿 |
|
返回顶楼 | |
发表时间:2005-03-18
frankensteinlin 写道 你就factory自己修改一下不久行了,指责不要太清楚哦!我才不管是远程的datasource还是本地的呢。
那么好了,我在生产环境要用JNDI取下来的datasource,在测试环境要用本地的datasource,那么这个factory我是不是要写两套,分别用在生产环境和测试环境?datasource你这么搞,transaction context是不是也要这么搞?message queue是不是也要这么搞?然后你要换一个环境,就要改七八个工厂的配置,你累不累? |
|
返回顶楼 | |
发表时间:2005-03-18
这叫正向控制,不叫反转控制,控制层次是由高到低,职责分明的。
public class 高档PC : PC { public 高档PC(); { } protected override void ConstructMe(); { m_cpu = CPUProvider.GetHightSpeedCPU();; m_memory = MemoryProvider.GetLargeMemory();; } } |
|
返回顶楼 | |
发表时间:2005-03-18
还掰您这“高档PC”呢。咱也不用说什么正置倒置,我就提一个问题。回头需要卖“中档PC”,你怎么办?再加一个class?需要卖“学生PC”,你怎么办?再加一个class?需要卖“老年PC”,你怎么办?再加一个class?需要卖“绿色PC”,你怎么办?再加一个class?别忘了,现在是细分人群炒作概念的年代,照您这做法,PC厂家每增加一个概念,您就得新建一个class,您这维护还不做死啊。
|
|
返回顶楼 | |