代码“中间地带”的封装与复用
2009-10-15 09:52
295 查看
先提出一个词:中间地带。
作为一个框架提供商,微软公司为我们提供了最基础最常用的类和方法,在实际工作中,我们需要去继承去组合这些类与方法,形成我们的解决方案。
那么,存在一个问题,为什么微软公司不为我们提供一个无所不包无所不能点一下鼠标就会出现的万能代码库呢?
因为……不现实。
有一个类Root,A需要这个类具备的功能列表假设为F(A),B需要这个类具备的功能列表为F(B),……,Z需要这个类具备的功能列表为F(Z)。
一个万能的解决方案是为这个控件实现F(God)=F(A)UF(B)UF(C)……UF(Z)这么多功能。而实际上,框架提供给我们的只有F(Root)=F(A)∩F(B) ∩F(C)……∩F(Z)这么少的功能。
对A来说,在F(Root)和F(A)之间,就存在一大片中间地带:F(Root)-F(A),如下图中的阴影部分。
[align=center]
public class CategoryItemSelectorMediator
{
protected List<CategoryItem> Items { get; set; }
protected ListBox BindedListBox { get; set; }
protected ComboBox BindedComboBox { get; set; }
protected TextBox BindedTextBox { get; set; }
public CategoryItemSelectorMediator()
{
Items = new List<CategoryItem>();
}
public event EventHandler<EventArgs> ListBoxItemDoubleClick;
protected virtual void OnListBoxItemDoubleClick(EventArgs e)
{
EventHandler<EventArgs> handler = ListBoxItemDoubleClick;
if (handler != null)
{
handler(this, e);
}
}
public void Bind(IEnumerable<CategoryItem> items, ComboBox comboBox, ListBox listBox, TextBox txtBox)
{
if (items == null) throw new ArgumentNullException("items");
if (comboBox == null) throw new ArgumentNullException("comboBox");
if (listBox == null) throw new ArgumentNullException("listBox");
if (txtBox == null) throw new ArgumentNullException("txtBox");
this.Items.Clear();
this.Items.AddRange(items);
this.BindedComboBox = comboBox;
this.BindedListBox = listBox;
this.BindedTextBox = txtBox;
this.BindedComboBox.SelectedIndexChanged += new EventHandler(BindedComboBox_SelectedIndexChanged);
this.BindedListBox.SelectedIndexChanged += new EventHandler(BindedListBox_SelectedIndexChanged);
this.BindedListBox.MouseDoubleClick += new MouseEventHandler(BindedListBox_MouseDoubleClick);
this.BindedComboBox.DataSource = this.GetCategorys();
BindListBox("全部");
}
private void BindedListBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
int itemRegionHeight = this.BindedListBox.Items.Count * this.BindedListBox.ItemHeight;
if (e.Y <= itemRegionHeight)
{
OnListBoxItemDoubleClick(EventArgs.Empty);
}
}
private void BindListBox(String category)
{
this.BindedListBox.DataSource = this.Find(category);
this.BindedListBox.DisplayMember = "Name";
}
private List<String> GetCategorys()
{
List<String> categorys = new List<string>();
categorys.Add("全部");
foreach (var item in Items)
{
Boolean find = false;
foreach (var c in categorys)
{
if (c == item.Category)
{
find = true;
break;
}
}
if (find == false) categorys.Add(item.Category);
}
return categorys;
}
private List<CategoryItem> Find(String categoryName)
{
if (categoryName == "全部") return this.Items;
else
{
List<CategoryItem> finds = new List<CategoryItem>();
foreach (var item in this.Items)
{
if (item.Category == categoryName) finds.Add(item);
}
return finds;
}
}
private void BindedComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
this.BindListBox(this.BindedComboBox.Text);
}
private void BindedListBox_SelectedIndexChanged(object sender, EventArgs e)
{
Object obj = this.BindedListBox.SelectedItem;
if (obj == null) this.BindedTextBox.Text = String.Empty;
else
{
CategoryItem item = obj as CategoryItem;
this.BindedTextBox.Text = item.Introduce;
}
}
public List<CategoryItem> SelectItems
{
get
{
List<CategoryItem> list = new List<CategoryItem>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null) list.Add(i);
}
return list;
}
}
public List<Object> SelectValues
{
get
{
List<Object> list = new List<Object>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null) list.Add(i.Value);
}
return list;
}
}
public List<T> GetSelectValues<T>()
{
List<T> list = new List<T>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null && i.Value != null) list.Add((T)(i.Value));
}
return list;
}
}[/align]
当我们期望某些对象或控件之间形成某种Mediator所规定的行为约束时,就new 一下这个Mediator,Bind一下,就OK了。
三、牢骚话
很不好意思的说,爬了这么多年的代码,俺还是不能理解什么是MVC、MVP,俺看不到理解这几个词对俺的代码有何帮助。俺只是看到了在现有的东东和要做的东东之间存在巨大的中间地带,这个中间地带有很多很多的重复劳动需要去消除。用扩展方法和Mediator清理中间地带后,世界清静了不少。
四、题外话
对于知识,俺觉得,还是掌握的越少越好——正应了伟人的那句话:
知识越多越反动
当你掌握了面向对象的那些规则之后,设计模式你可以全部忘记了——那是枷锁。
当你掌握了DRY之后,面向对象的那些规则也可以全部忘记了——那是枷锁。
DRY就是Don't Repeat Yourself。用俺的话说,就是:不要复制和粘帖,那是邪恶滴。换一句话说就是,懒惰是程序员最佳的品质。
DRY是外语,不友好。“懒惰”歧义太多。还是俺的话最好理解:
对程序员来说,每一次的复制和粘帖都是在犯罪。
今天,你犯罪了吗?
补充:
这篇博客发出去之后,发现遗漏了一个观点。
有两种方法。
一种是拿着锤子去找钉子:学了一个东东,然后去找怎样去应用它。学一个模式,然后去全世界找实例。
一种是拿着钉子去找锤子:有一个问题,然后去找解决它的方法。用这个方式来看,用户控件和Mediator是同等的存在,虽然,它们分属不同的知识体系。
当你按一次Ctrl+C,按一次Ctrl+V时。说明你的程序必然存在不完美。如何去克服这种不完美。使用语法糖也好,设计模式也好,当猫道狗道全部用上也无法解决问题时再去Ctrl+C,Ctrl+V。长久以往,啥都理解了。
Ctrl+C, Ctrl+V,就是程序开发中的红灯。
作为一个框架提供商,微软公司为我们提供了最基础最常用的类和方法,在实际工作中,我们需要去继承去组合这些类与方法,形成我们的解决方案。
那么,存在一个问题,为什么微软公司不为我们提供一个无所不包无所不能点一下鼠标就会出现的万能代码库呢?
因为……不现实。
有一个类Root,A需要这个类具备的功能列表假设为F(A),B需要这个类具备的功能列表为F(B),……,Z需要这个类具备的功能列表为F(Z)。
一个万能的解决方案是为这个控件实现F(God)=F(A)UF(B)UF(C)……UF(Z)这么多功能。而实际上,框架提供给我们的只有F(Root)=F(A)∩F(B) ∩F(C)……∩F(Z)这么少的功能。
对A来说,在F(Root)和F(A)之间,就存在一大片中间地带:F(Root)-F(A),如下图中的阴影部分。
[align=center]
public class CategoryItemSelectorMediator
{
protected List<CategoryItem> Items { get; set; }
protected ListBox BindedListBox { get; set; }
protected ComboBox BindedComboBox { get; set; }
protected TextBox BindedTextBox { get; set; }
public CategoryItemSelectorMediator()
{
Items = new List<CategoryItem>();
}
public event EventHandler<EventArgs> ListBoxItemDoubleClick;
protected virtual void OnListBoxItemDoubleClick(EventArgs e)
{
EventHandler<EventArgs> handler = ListBoxItemDoubleClick;
if (handler != null)
{
handler(this, e);
}
}
public void Bind(IEnumerable<CategoryItem> items, ComboBox comboBox, ListBox listBox, TextBox txtBox)
{
if (items == null) throw new ArgumentNullException("items");
if (comboBox == null) throw new ArgumentNullException("comboBox");
if (listBox == null) throw new ArgumentNullException("listBox");
if (txtBox == null) throw new ArgumentNullException("txtBox");
this.Items.Clear();
this.Items.AddRange(items);
this.BindedComboBox = comboBox;
this.BindedListBox = listBox;
this.BindedTextBox = txtBox;
this.BindedComboBox.SelectedIndexChanged += new EventHandler(BindedComboBox_SelectedIndexChanged);
this.BindedListBox.SelectedIndexChanged += new EventHandler(BindedListBox_SelectedIndexChanged);
this.BindedListBox.MouseDoubleClick += new MouseEventHandler(BindedListBox_MouseDoubleClick);
this.BindedComboBox.DataSource = this.GetCategorys();
BindListBox("全部");
}
private void BindedListBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
int itemRegionHeight = this.BindedListBox.Items.Count * this.BindedListBox.ItemHeight;
if (e.Y <= itemRegionHeight)
{
OnListBoxItemDoubleClick(EventArgs.Empty);
}
}
private void BindListBox(String category)
{
this.BindedListBox.DataSource = this.Find(category);
this.BindedListBox.DisplayMember = "Name";
}
private List<String> GetCategorys()
{
List<String> categorys = new List<string>();
categorys.Add("全部");
foreach (var item in Items)
{
Boolean find = false;
foreach (var c in categorys)
{
if (c == item.Category)
{
find = true;
break;
}
}
if (find == false) categorys.Add(item.Category);
}
return categorys;
}
private List<CategoryItem> Find(String categoryName)
{
if (categoryName == "全部") return this.Items;
else
{
List<CategoryItem> finds = new List<CategoryItem>();
foreach (var item in this.Items)
{
if (item.Category == categoryName) finds.Add(item);
}
return finds;
}
}
private void BindedComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
this.BindListBox(this.BindedComboBox.Text);
}
private void BindedListBox_SelectedIndexChanged(object sender, EventArgs e)
{
Object obj = this.BindedListBox.SelectedItem;
if (obj == null) this.BindedTextBox.Text = String.Empty;
else
{
CategoryItem item = obj as CategoryItem;
this.BindedTextBox.Text = item.Introduce;
}
}
public List<CategoryItem> SelectItems
{
get
{
List<CategoryItem> list = new List<CategoryItem>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null) list.Add(i);
}
return list;
}
}
public List<Object> SelectValues
{
get
{
List<Object> list = new List<Object>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null) list.Add(i.Value);
}
return list;
}
}
public List<T> GetSelectValues<T>()
{
List<T> list = new List<T>(this.BindedListBox.SelectedItems.Count);
foreach (var item in this.BindedListBox.SelectedItems)
{
CategoryItem i = item as CategoryItem;
if (i != null && i.Value != null) list.Add((T)(i.Value));
}
return list;
}
}[/align]
当我们期望某些对象或控件之间形成某种Mediator所规定的行为约束时,就new 一下这个Mediator,Bind一下,就OK了。
三、牢骚话
很不好意思的说,爬了这么多年的代码,俺还是不能理解什么是MVC、MVP,俺看不到理解这几个词对俺的代码有何帮助。俺只是看到了在现有的东东和要做的东东之间存在巨大的中间地带,这个中间地带有很多很多的重复劳动需要去消除。用扩展方法和Mediator清理中间地带后,世界清静了不少。
四、题外话
对于知识,俺觉得,还是掌握的越少越好——正应了伟人的那句话:
知识越多越反动
当你掌握了面向对象的那些规则之后,设计模式你可以全部忘记了——那是枷锁。
当你掌握了DRY之后,面向对象的那些规则也可以全部忘记了——那是枷锁。
DRY就是Don't Repeat Yourself。用俺的话说,就是:不要复制和粘帖,那是邪恶滴。换一句话说就是,懒惰是程序员最佳的品质。
DRY是外语,不友好。“懒惰”歧义太多。还是俺的话最好理解:
对程序员来说,每一次的复制和粘帖都是在犯罪。
今天,你犯罪了吗?
补充:
这篇博客发出去之后,发现遗漏了一个观点。
有两种方法。
一种是拿着锤子去找钉子:学了一个东东,然后去找怎样去应用它。学一个模式,然后去全世界找实例。
一种是拿着钉子去找锤子:有一个问题,然后去找解决它的方法。用这个方式来看,用户控件和Mediator是同等的存在,虽然,它们分属不同的知识体系。
当你按一次Ctrl+C,按一次Ctrl+V时。说明你的程序必然存在不完美。如何去克服这种不完美。使用语法糖也好,设计模式也好,当猫道狗道全部用上也无法解决问题时再去Ctrl+C,Ctrl+V。长久以往,啥都理解了。
Ctrl+C, Ctrl+V,就是程序开发中的红灯。
相关文章推荐
- [Delphi]DLL封装登录框架实现代码复用
- iOS系统弹框封装 一句代码实现中间和底部弹框
- DLL封装登录框架实现代码复用
- 使用元组封装变量(java泛型的利用) 达到代码复用的目的
- AngularJS之使用服务封装可复用代码
- DLL封装登录框架实现代码复用
- 我的文章《DLL封装登录框架实现代码复用》终于要发表了
- react native 封装组件以复用
- php制作圆形用户头像的实例_自定义封装类源代码
- 复制所有属性进行继承 转自 博客园 汤姆大叔 深入理解JavaScript系列(46):代码复用模式(推荐篇)
- 面向对象的分析设计程序思想通过封装、继承、多态将程序耦合度降低,使程序更加灵活、容易修改和易于复用。
- PHP代码的多继承 -》 PHP代码复用新的姿势 trait
- 使用VB将ASP代码封装生成DLL文件
- 【Android】Android 自定义View 代码复用
- javascript代码复用模式(二)
- 多路复用I/O模型select() 模型 代码实现
- 面向对象封装分页代码
- 由mybatis的逆向工程看如果使用封装代码(深入理解java面向对象的思维逻辑)
- 05-调度函数的封装与代码模块化
- 代码复用的规则