1 Aug
封装不封装,这是个问题。
今天我在看Cocoa开发者邮件列表的时候,看到一个帖子,求助如何在两个VIEw之间互相通信的问题。做windows程序员的时间长的我都不好意思说了,我意识到,这个问题在我刚刚接触到Mac上的Objective-C时也遇到过。
我现在可以提出这个问题的简化版:“我有一个对话框,获取了一些用户输入的数据。我现在需要从我那个对话框中把这个数据提取出来以供主窗口使用。如何才能从主窗口获取到对话框里的数据呢?”
本文作者是强悍的Matt Long,作者首发于cimgf,由cocoachina翻译给广大读者。原文地址在这里。文中的“我”指作者。
在windows里,尤其是C# .NET,你可以通过添加一个Form对象来创建新的窗口,而且还可以简单地在设计窗口中添加一些不同的“控件”。这些 *** 作是非常容易的。不过一旦窗口创 建好之后,你需要在主窗口的代码中建立刚才新建的窗口的实例,然后提供公共变量在两个窗口之间设置或者获取数据。窗口类是由windows Form模板写好直接交给你使用的,这当然可以使代码看起来清晰干净,但是它打破了MVC的惯例,所以大部分windows的程序员会花费不少时间提升他 们思考的方式也就不足为奇了。
我用VS2008做了一个demo程序,截图大概是这样的:
看一下主窗口的代码:
public partial class Form1 : Form { Panel p; ? public Form1 ( ) { InitializeComponent ( ); p = new Panel ( ); p. Show ( ); } ? private voID btnChangeText_Click ( object sender,EventArgs e ) { p. OutputText = this. tbinputText. Text; } }
注意看我声明了一个Panel的对象,这是我们需要在上面设置文字的第二个窗口(vIEw)。下面是Panel类的代码:
public partial class Panel : Form { public Panel ( ) { InitializeComponent ( ); } ? public string OutputText { set { this. tbOutputText. Text = value; } } }
好,代码很容易理解,但是从这里就可以看出我的观点:MVC模型已经被破坏了。虽然这个例子里面并没有任何编程逻辑,不过很清楚的是这样的设计导致你只需要把代码放到按钮的事件处理里面就可以了,而不是去将逻辑抽象到controller对象中。
你也许会问,我在C#中如何做MVC呢?呃……这是一个关于Objective-C、Cocoa编程的网站,对于读者们来说这是个作业了……不过坦 白讲,我可不知道。我知道那是一件可能的事情,不过C#语言的内部就没有把开发者向这个方向去引导。我也看过一些讲这方面事情的文章,不过那些也都是基本 上困难到没法实践的。有几篇号称是MVC不过根本不算,所以如果你真想在C#上面实现MVC,自己想办法弄吧……^o^ 我想说的其实就是要想在C#上面实现MVC,那算你狠。
Objective-C/Cocoa的方式
在Objective-C里,你必须明确地创建一个controller用来处理model和vIEw之间的变化。其实MVC应该被称做MCV,因 为controller是在model和vIEw之间的一个协调员。如果你的model发生了改变,你的controller会通知vIEw。如果用户在 vIEw中做出了某种改变,controller就会通知model。所以我建议初学者可以叫它MCV,会更加形象一点。有点跑题了。
在Objective-C/Cocoa的世界里,我们建立的controller通常是指应用程序(Application)的托管 (Delegate),或者可以简单称做app delegate。很多windows程序员都会在这里迷惑不解的事情是,我们通常学习到的面向对象开发就是你应该去做的事情,而并不会关注为什么你会去 做,或者你为什么不去做。我并不是说你别用OOP的思想,而正相反我建议去用。问题是如果把一切都抽象化,那就有点太傻叉了……我们应该有很好的理由去写 这些代码,而不要用诸如“我从大学里面学的……”或是“我一直就这么干……”这种理由。
当你在Objective-C里面建立一个app delegate的时候,这个delegate可以做为你所有model和vIEw的controller,或者你也可以为不同的model和vIEw分 别创建controller。想怎么干就怎么干吧。不过有一个比较重要的事情是要记住的,如果你把所有的代码都扔到同一个app delegate类里头,那你就有了一个超大的app delegate文件,很难看清楚。
一些例子程序
为了帮助那个提出问题的朋友,还有另外一些想从windows开发转变到Cocoa开发的朋友们,我也写了点简单例子来帮助把这个问题变简单。如果 你想让两个VIEw,或者两个窗口可以互相之间通信,只要在他们之间传递消息就可以了。虽然把你的vIEw们封装到它们自己的类中并不是坏事,不过通常来 说真的没必要。在任何一种语言和任何一种平台上,都有实现这个功能的方法,所以就别管我没提到的事情了,我也没说这是唯一的方法不是……我说的方法是简单 直接的方法,可以帮你更快的理解。
我同样建了一个简单的demo程序来演示上面说的,这里是截图:
你可以在这里下载例子。
这里是我提到的代码,只需要在app delegate的头文件中将你的vIEw声明为outlet:
@interface AppDelegate : NSObject { IBOutlet NSTextFIEld *inputText; IBOutlet NSTextFIEld *outputText; }
然后声明这样一个方法,在按下按钮之后会执行:
- (IBAction )updateText : ( ID ) sender;
最好要做的事情就是在IB里面把action和outlet连到AppDelegate对象上,任务完成。就这么简单。
为什么windows的方法烂,Mac的方法赞
好吧,这个小标题仅仅是个玩笑,windows专家们千万表喷俺。不过我的确认为C#设计用户界面的方式会把人们的代码搞得贼乱,而且明显不是MVC模式。
当然,又来了,怎么做还是看你自己,不过.NET的用户界面设计工具非常鼓励用户去破坏MVC模式。当你在设计器里面把一个按钮拽到窗口里,然后双 击那个按钮的时候,它就自动地给你指到按钮点击事件代码里,大部分程序员就自然而然地在那里写代码了。当你在设计过程的时候,倒也没什么,不过它根本没有 做什么来支持你将逻辑和表现分开。
在Objective-C里,想破坏MVC设计模式倒是很困难的事情。基本上你都必须遵循这个模式。甚至当你使用Interface Builder在app delegate和action及outlet中间建立连接的时候,都会带有一个可视的MVC表现。要连接app delegate类(你的controller)到outlet的时候(比如输入框),你按住ctrl之后从AppDelegate拖拽一根线放到 outlet上。当你想告诉AppDelegate执行一些动作,你要从触发动作的对象中拽到AppDelegate对象上。反过来是不行的。养成这样的 习惯其实很好,只不过windows的铁杆程序员会相当不习惯。
结论
从windows程序员转到Mac程序员是有一点挑战的,不过你越早抛掉从前的开发的概念,就越容易接受Mac开发的概念。想想令狐冲吧……Mac的开发的确是不太一样的。要习惯这种开发思路,而不要试图沿用从前的习惯来进行Mac开发。
承认这一点吧兄弟们,工程师们都是很傲慢的,而且当学习一门新的语言、技术或是平台的时候,通常会认为他们已经很清楚了。最后这句的英文真的很棒, 我不知道怎么翻译才能完美的表达这句话,和大家共勉:Goto is not inherently evil,you kNow? Until next time.
子分类: NSWindow,初学者,基础知识如果您有疑问,可以去讨论区询问 本文章评论的RSS feed TrackBack URI 17 Responses for "Cocoa教学:windows OOP与Cocoa MVC之对比" eric.leopard 08月 2nd,2008 at 12:36 am 1
呵呵,的确如此,windows 程序的很多设计思路破坏了MVC,或者MVC不够彻底,导致像我这样的懒人越学越乱,越编越没有章法,到是mac开发来的痛快:这就是游戏规则,你必须得遵守。 初学者如果按照这种思路学可以养成良好得习惯 -_-
iphone、mac开发者交流群:66407575,欢迎大家一起来讨论
Huajun 08月 2nd,2008 at 2:15 am 2写得非常好
zeta 08月 2nd,2008 at 11:50 am 3我在大学得时候就疯狂迷上了apple得软件设计哲学,从此非常不喜欢windows得那一套。
而且我觉得mac是最适合学计算机学生使用得电脑,用mac做编程是多么愉快得事情。
最后为啥要想想令狐大侠呢? 小生不明啊….
很有启发的文章,学习了!
正在投向cocoa~
谢谢!
无招胜有招……先把过去的东西忘掉,再去接受新的东西:)
想想令狐冲 08月 17th,2008 at 12:23 am 6小生一直反感windows下的开发….所以压根没接受visual studio 和 C# …
现在基本上用windows也是开SSH到linux下工作了,渐渐脱离….
小生只会C,脑子里过去的记忆也只有c的种种…用Objective-C还是不能忘记c吧…
最近在看 <>发现上边的例子全是C#,郁闷…打算自己用Objective-C重写一遍~加油!
最近在看… 大话设计模式
Grey 08月 20th,2008 at 10:02 am 8就 像你说不要什么都抽象为oo一样,什么都MVC也未必好。java的struts框架和ruby的rails都是mvc的。其实很多地方根本不需要这么复 杂。就像本站,PHP。vb(非vb.net)是个纯面向事件的,基本不oo不mvc,但是做小型开发不得不说它快速,方便,简洁。
微软出手就是把什么都变简单,当然也是把程序员变傻(比如用.net开发web程序的经常搞不清客户端程序和服务器端程序的区别。因为微软就根本把这个隐藏起来了。),不可否认,“简单”这个词吸引了很多程序员和公司啊。时间就是生命。
不过我倒是喜欢cocoa的。
要说把事情变简单,我就没看过有什么比Delphi做的更好的。“发明”了COM系列,.NET系列的微软,简单问题复杂化才是他最大的办事。
GlIDer 08月 28th,2008 at 3:48 pm 10可能楼上的不知道,delphi的首席构架师,跳槽到微软后出来的就是.Net(这人可是盖茨亲自三顾茅庐请来的)。我曾经迷过一段时间编译器,对此人是顶礼膜拜。
GlIDer 08月 28th,2008 at 4:04 pm 11我两个平台都还算比较熟悉,这里的比较其实与其叫模式的比较,还不如叫语言的比较。C++对比ObjectiveC,ObjectiveC的动态特性对于实现MVC有先天的优势。而C++的这种强类型语言要达到类似目标需要很多额外的工作。
这个与windows或者Mac开发本身无关,至少我是这么认为的。其实Carbon的模式比VC还要可怕很多,开发起来对于新手来说就是个地狱。Cocoa完全是沾了ObjectiveC的光才能如此美妙。
但天下没有免费的午餐,ObjetiveC的效率与真正的C++比较起来有差距的。尤其是Cocoa推崇KVC模式,效率更不敢恭维。
最后,Cocoa的Binding破坏了这个模式,如果不熟悉CocoaBinding,看使用了Binding的Cocoa程序,会让人发懵的。
www.superarts.org 08月 29th,2008 at 3:31 pm 12跳槽过去的主要产品好像是C#吧?C#借鉴了Delphi的“让语言迁就架构”的思路,对于单平台的开发者来说还是很不错的。我所谓.NET把简单问题复杂化的意思是,对比POSIX这种几十年不变但一直在用的标准,.NET升级太乱,太快,用户要不断学习,代价比较大。
www.superarts.org 08月 30th,2008 at 12:14 pm 13我说错了,Anders是C#的首席设计师的同时也是.NET架构的重要开发者。C#和.NET的关系就像Delphi和VCL/clx,怎么会分开呢……
在私有软件领域他的贡献是很大的,除了现代产品的主设计师之外,他是Turbo Pascal的原始作者。这一点也展现了他的技术前瞻性。确实现在还有像我一样干什么都用VIM的人,但在人数上,用IDE的是远远为多的。
微软:
He is the chIEf designer of the C# programming language and a key participant in the development of the Microsoft .NET framework.
的确如此,完全没有window开发经验的话会更快的接受cocoa的开发模式
noname 09月 10th,2008 at 5:26 pm 15为了模式而模式,太没必要了。
做过大产品的都知道,什么模式、架构都是市场推广的手段,实际上没什么用。
自己会架构当然无所谓。但多数程序员没这个水平吧。
@H_404_744@ Darling 11月 26th,2008 at 4:06 am 17正在学习编程,很讨厌VS Studio,不过还是要做作业。下个学期实习,好好的学学苹果的编程,不要浪费了我的小白吗!哈哈 到时候,要麻烦贵网站了。
总结以上是内存溢出为你收集整理的Cocoa教学:Windows OOP与Cocoa MVC之对比全部内容,希望文章能够帮你解决Cocoa教学:Windows OOP与Cocoa MVC之对比所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)