最近在敲大话设计模式中的C#代码.我是在看UML图去敲代码的.由于UML图中没有画出客户端的图.
导致写客户端的代码时,很是费力.不清楚该怎么写.没有一点的章法.总是蒙几句.最后运行出来了,感觉就是
对的,也不知道自己是怎么写出来的.让我从头写一次.和上次的感觉还是一样的.我仔细分析了一下.

关于为什么不会写客户端.我感觉这不是一个单纯的编码问题.也不是你对语言的理解不深刻.

其实是你对程序的过程理解不深刻,对各个类的职能不理解.对面向对象不理解.

我这里只讨论控制台程序.
比如一个程序你不会写客户端,其实你就是不知道客户是如何调用它的.
这个面向对象的技术有很大关系.你的程序已近都把你将要用的类,功能编写完毕了.那么客户端是什么呢?
其实就是你如何去实例化这些类,那些类该实例化,在那个时候实例化.让他们变成能工作的具体对象.然后
是如何利用这些对象的方法.也就是功能.

我们往往感到困惑的地方就是如何实例化这些类.很多的时候客户端要体现OO的多态特征.要用父类去实
例化子类,如果你直接运用了子类实例化自己.其实反映出来的就是你对多态的不理解.为什么要用多态,
个人理解一是:为了程序的灵活性,父类可以实例化很多的子类,不用一个一个的判断我要用到那个子类,
然后再去实例化,减轻了客户端的负担.二是: 为了方便调用,调用的时候,我客户端不需要知道你到底是那个
子类的方法,只需要调用父类的同样的方法,就能控制子类.

能快速高效的把客户端写好,证明这个程序的思路你就已近理解了.下面举一个例子来说明一下:

就拿设计模式中的<适配器模式>来说(c#)

首先你先设计出各个类.就好像是你要做饭先把各个料备好.

1: //抽象父类球员,每个人都有进攻,防守方法
2:     abstract class Player
3:     {
4:         protected string name;
5:         public Player(string name)
6:         {
7:             this.name = name;
8:         }
9:         public abstract void Attack();
10:         public abstract void Defense();
11:     }
1: //具体球员前锋类
2:     class Forwards : Player
3:     {
4:         public Forwards(string name)
5:             : base(name)
6:         { }
7:
8:         public override void Attack()
9:         {
10:             Console.WriteLine("前锋{0} 进攻", name);
11:         }
12:         public override void Defense()
13:         {
14:             Console.WriteLine("前锋" + name + "防守");
15:         }
16:
17:     }
1: //具体球员后卫类,继承player
2:     class Guard : Player
3:     {
4:         public Guard(string name)
5:             : base(name)
6:         { }
7:         public override void Attack()
8:         {
9:             Console.WriteLine("后卫{0} 进攻 ", name);
10:         }
11:         public override void Defense()
12:         {
13:             Console.WriteLine("后卫" + name + "防守");
14:         }
15:     }
1:  //外籍球员类,注意没有继承player,说明他直接和其他队员不能沟通
2:     class ForeignCenter
3:     {
4:         private string name;
5:         public string Name
6:         {
7:             get { return name; }
8:             set { name = value; }
9:         }
10:         public void jingong()
11:         {
12:             Console.WriteLine("外籍中锋{0}进攻 ", name);
13:         }
14:         public void fangshou()
15:         {
16:             Console.WriteLine("外籍中锋{0}防守 " ,name);
17:         }
18:     }
1: //外籍球员的翻译人员.继承player,说明是他和其他球员沟通
2:     class Translator : Player
3:     {
4:         private ForeignCenter fc = new ForeignCenter();
5:
6:         public Translator(string name)
7:             : base(name)
8:         {
9:             fc.Name = name;
10:         }
11:         public override void Attack()
12:         {
13:             fc.jingong();
14:         }
15:         public override void Defense()
16:         {
17:             fc.fangshou();
18:         }
19:     }


所以的料都备好以后.开始做饭:也就是写客户端.
首先要打球,我们就要有队员.
(1)实例化队员,队员就包括前锋,后卫,中锋都要有

Player f = new Forwards("巴蒂尔");
Player g = new Guard("阿尔斯通");

这里很明显的一点就是用父类去实例化子类的构造方法.能让人很好的理解.这些人都是球员.体现了多态.这样做.当有特殊条件的时候,就可以用特殊条件实例化(见试验二).方便吧.

(2)对于中锋因为他是一个外籍球员,我们当然不能和其他人一样对待.注意刚才我们写类的时候,中锋没有继承player,而是翻译
说明我们要实例化的时候,就是给外籍中锋配一个翻译.

Player ym = new Translator("姚明");
这个翻译让姚明干什么,姚明就去干什么(这个本人感觉很像是代理模式).

(3)然后就是下锅了,谁有什么本事就使出来.能发甜的发甜,发辣的发辣.
也就是调用他们的方法.

 

1: f.Attack();
2: f.Defense();
3: g.Attack();
4: g.Defense();
5: ym.Attack();
6: ym.Defense();


试验一:

前面说用父类去实例化子类,那么我们可不可以用子类实例化自己呢?当然可以,这个体现了"里氏代换原则".子类必需能替换它的父类.
代码如下:
Forwards f = new Forwards("巴蒂尔");
Guard g = new Guard("阿尔斯通");

结果和刚才的一样:

这就说明在客户端的编写过程中,其实能达到效果的不只是一种,你要选择最方便,最有效的方式.

试验二:
那么用父类去实例化子类有什么好处呢?当然 这个主要是体现多态性.在实例化的子类比较多的时候是比较实用的
比如我们要选择实例化了球员时 .这样就有很好的价值了>
代码

1:        Player p=null;  //修改之处.将p初始化为null.
2:             Console.WriteLine("请选择球员");
3:             string type = Console.ReadLine();
4:
5:             switch (type)
6:             {
7:                 case "1":
8:                     p = new Forwards("巴蒂尔");
9:                     break;
10:                 case "2":
11:                     p = new Guard("阿尔斯通");
12:                     break;
13:             }
14:             p.Attack();
15:             p.Defense();
16:             Player ym = new Translator("姚明");
17:             ym.Attack();
18:             ym.Defense();


总结:在写客户端的时候,我们要清晰我们需要那些材料,然后用怎么样的顺序,方法去实例化它.最后让实例化的
对象去做什么.这是本人的一点感悟,欢迎大家拍砖.


最近在敲大话设计模式中的C#代码.我是在看UML图去敲代码的.由于UML图中没有画出客户端的图.
导致写客户端的代码时,很是费力.不清楚该怎么写.没有一点的章法.总是蒙几句.最后运行出来了,感觉就是
对的,也不知道自己是怎么写出来的.让我从头写一次.和上次的感觉还是一样的.我仔细分析了一下.

关于为什么不会写客户端.我感觉这不是一个单纯的编码问题.也不是你对语言的理解不深刻.

其实是你对程序的过程理解不深刻,对各个类的职能不理解.对面向对象不理解.

我这里只讨论控制台程序.
比如一个程序你不会写客户端,其实你就是不知道客户是如何调用它的.
这个面向对象的技术有很大关系.你的程序已近都把你将要用的类,功能编写完毕了.那么客户端是什么呢?
其实就是你如何去实例化这些类,那些类该实例化,在那个时候实例化.让他们变成能工作的具体对象.然后
是如何利用这些对象的方法.也就是功能.

我们往往感到困惑的地方就是如何实例化这些类.很多的时候客户端要体现OO的多态特征.要用父类去实
例化子类,如果你直接运用了子类实例化自己.其实反映出来的就是你对多态的不理解.为什么要用多态,
个人理解一是:为了程序的灵活性,父类可以实例化很多的子类,不用一个一个的判断我要用到那个子类,
然后再去实例化,减轻了客户端的负担.二是: 为了方便调用,调用的时候,我客户端不需要知道你到底是那个
子类的方法,只需要调用父类的同样的方法,就能控制子类.

能快速高效的把客户端写好,证明这个程序的思路你就已近理解了.下面举一个例子来说明一下:

就拿设计模式中的<适配器模式>来说(c#)

首先你先设计出各个类.就好像是你要做饭先把各个料备好.

1: //抽象父类球员,每个人都有进攻,防守方法
2:     abstract class Player
3:     {
4:         protected string name;
5:         public Player(string name)
6:         {
7:             this.name = name;
8:         }
9:         public abstract void Attack();
10:         public abstract void Defense();
11:     }
1: //具体球员前锋类
2:     class Forwards : Player
3:     {
4:         public Forwards(string name)
5:             : base(name)
6:         { }
7:
8:         public override void Attack()
9:         {
10:             Console.WriteLine("前锋{0} 进攻", name);
11:         }
12:         public override void Defense()
13:         {
14:             Console.WriteLine("前锋" + name + "防守");
15:         }
16:
17:     }
1: //具体球员后卫类,继承player
2:     class Guard : Player
3:     {
4:         public Guard(string name)
5:             : base(name)
6:         { }
7:         public override void Attack()
8:         {
9:             Console.WriteLine("后卫{0} 进攻 ", name);
10:         }
11:         public override void Defense()
12:         {
13:             Console.WriteLine("后卫" + name + "防守");
14:         }
15:     }
1:  //外籍球员类,注意没有继承player,说明他直接和其他队员不能沟通
2:     class ForeignCenter
3:     {
4:         private string name;
5:         public string Name
6:         {
7:             get { return name; }
8:             set { name = value; }
9:         }
10:         public void jingong()
11:         {
12:             Console.WriteLine("外籍中锋{0}进攻 ", name);
13:         }
14:         public void fangshou()
15:         {
16:             Console.WriteLine("外籍中锋{0}防守 " ,name);
17:         }
18:     }
1: //外籍球员的翻译人员.继承player,说明是他和其他球员沟通
2:     class Translator : Player
3:     {
4:         private ForeignCenter fc = new ForeignCenter();
5:
6:         public Translator(string name)
7:             : base(name)
8:         {
9:             fc.Name = name;
10:         }
11:         public override void Attack()
12:         {
13:             fc.jingong();
14:         }
15:         public override void Defense()
16:         {
17:             fc.fangshou();
18:         }
19:     }


所以的料都备好以后.开始做饭:也就是写客户端.
首先要打球,我们就要有队员.
(1)实例化队员,队员就包括前锋,后卫,中锋都要有

Player f = new Forwards("巴蒂尔");
Player g = new Guard("阿尔斯通");

这里很明显的一点就是用父类去实例化子类的构造方法.能让人很好的理解.这些人都是球员.体现了多态.这样做.当有特殊条件的时候,就可以用特殊条件实例化(见试验二).方便吧.

(2)对于中锋因为他是一个外籍球员,我们当然不能和其他人一样对待.注意刚才我们写类的时候,中锋没有继承player,而是翻译
说明我们要实例化的时候,就是给外籍中锋配一个翻译.

Player ym = new Translator("姚明");
这个翻译让姚明干什么,姚明就去干什么(这个本人感觉很像是代理模式).

(3)然后就是下锅了,谁有什么本事就使出来.能发甜的发甜,发辣的发辣.
也就是调用他们的方法.

 

1: f.Attack();
2: f.Defense();
3: g.Attack();
4: g.Defense();
5: ym.Attack();
6: ym.Defense();


试验一:

前面说用父类去实例化子类,那么我们可不可以用子类实例化自己呢?当然可以,这个体现了"里氏代换原则".子类必需能替换它的父类.
代码如下:
Forwards f = new Forwards("巴蒂尔");
Guard g = new Guard("阿尔斯通");

结果和刚才的一样:

这就说明在客户端的编写过程中,其实能达到效果的不只是一种,你要选择最方便,最有效的方式.

试验二:
那么用父类去实例化子类有什么好处呢?当然 这个主要是体现多态性.在实例化的子类比较多的时候是比较实用的
比如我们要选择实例化了球员时 .这样就有很好的价值了>
代码

1:        Player p=null;  //修改之处.将p初始化为null.
2:             Console.WriteLine("请选择球员");
3:             string type = Console.ReadLine();
4:
5:             switch (type)
6:             {
7:                 case "1":
8:                     p = new Forwards("巴蒂尔");
9:                     break;
10:                 case "2":
11:                     p = new Guard("阿尔斯通");
12:                     break;
13:             }
14:             p.Attack();
15:             p.Defense();
16:             Player ym = new Translator("姚明");
17:             ym.Attack();
18:             ym.Defense();


总结:在写客户端的时候,我们要清晰我们需要那些材料,然后用怎么样的顺序,方法去实例化它.最后让实例化的
对象去做什么.这是本人的一点感悟,欢迎大家拍砖.