设计模式之 面向对象的养猪厂的故事,C#演示(一)

对于设计模式, 从本质上说, 其最大的用途就是适应需求的变化. 因为有了设计模式,我们可以在设计阶段就为未来可能发生的变化留下足够的空间.

我们通过一个建造现代化养猪场的故事, 来讨论一下设计模式与需要变化之间的关系.

(一)设计模式最根本的意图是适应需求的变化

一个机器人研发小组研制了一种能自动喂猪的机器人, 于是有人投资兴建了一座由机器人管理的养猪场. 这个养猪场要饲养的猪的品种包括:

  • 大白猪: 又叫"大约克郡猪", 原产于英国. 全身白色,耳向前挺立,体长大,成年公猪体重三百到五百公斤,繁殖力强, 是全世界分布最广的猪型.
  • 长白猪: 是"兰德瑞斯猪" 在中国的统称. 著名的腌肉型猪, 原产于丹麦. 全身白色, 体躯 特长, 耳大前垂, 背腰平直, 大腿丰满. 皮薄瘦肉多.成年公猪体重四百到五百公斤, 要求较好的饲养管理条件.
  • 波中猪: 是猪的著名品种, 原产于美国, 属脂肪型, 已培育成肉用型. 全身黑色.成年公猪重三百九十到四百五十公斤, 早熟易肥, 但繁殖力较弱.

下面我们来讨论机器人小组的设计方案:

                  图v1-1

用UML绘制的养猪场v1.0软件动作机制如图V1-1所示。最初的设计因为猪场只引进了大白猪品种,所以没有考虑饲养其它种类猪的情况。

一个喂猪机器人管理了若干头大白猪。由于猪天性懒惰,机器人必须把饲料放到猪嘴边,然后吆喝一句,“大白猪,吃!”,猪才会进食。

在v1.0版的程序动作下,养猪场运行状况相当不错,每头猪都养得膘肥休壮,如果不是企业要不断的追求剩余价值,我们的故事也许就到此结束了。

随着养猪场的蓬勃发展,养猪场老板决定进军国际市场。可是,不同地方的人喜欢吃不同品种的猪。为了适应这一需求的变化,养猪场新引进了一批长白猪。

问题出现了:喂猪机器人照例把饲料准备好,拿到每一头猪面前,大叫一声:”大白猪,吃!“,大白猪能像往常一样愉快地进食。但轮到长白猪时,长白猪无动于衷。这下急坏了养猪场的老板。为了解决问题,喂猪机器人的研发团队紧急出动,当晚便改好了程序。
V2.0 程序如图v2-1所示:

                      图v2-1

经过此次修改,喂猪机器人在对待每一头猪时,会先辩认出这头猪的类型,如果这是一头大白猪,它就会大叫一声”大白猪,吃!“,如果是一头长白猪,就叫”长白猪,吃“,经过这一个性,养猪场又恢复了平静。

可刚过了几天,类似的问题又再次出现,养猪场引进了几头波中猪!这下,机器人又不知道怎么喂了。研发团队又准备大动干戈、修改代码了。老板却对研发团队的做法表示不理解:“你们太不像话了,我是付了钱的,可每次我要扩大再生产的时候,你们都要耽误我好几天时间,重新修改什么代码,如果下次我要养鸡、养青蛙了呢?”

这个现代化养猪场出现的问题其实就是需求变化的问题。设计模式可以使系统很容易地在某一特定的层面上适应需求的变化。使用设计模式后,系统就可以很好的满足开闭原则:我们不用修改原来的代码,而只需要添加新的代码就可以满足新的需求了。

从这个角度来看,使用设计模式的关键是预测未来可能发生的需求变化,并在设计过程中选用合适的设计模式。同时,我们也应该将设计模式应用于系统中那些明显不稳定、极可能发生变化的部分,而不应该为了体验创造的乐趣,把设计模式应用于那些永远不会发生变化的组件中去。

例如,在养猪场系统中,当养猪场头一回引进新品种长白猪时,我们就敏锐立即认识到猪的种类是一种易变的因素,这时就必须引入设计模式以适应这种需求的变化。

从这里我们可总结出有关设计模式的第一个核心设计原则:

设计模式最根本的意图是适应需求的变化,我们应只对变化或者可能变化的部分使用设计模式,对于不变的部分滥用设计模式就会造成“过渡设计”。

(二) 针对接口编程,而不要针对实现编程

现在,我们来看一下如何改进这个现代化养猪场的设计,使其能最大限度地适应需求变化。
首先,我们应该际加一个猪的抽象接口,该接口中定义了每一类猪共有的行为,而大白猪和长白猪则具体实现这些行为。系统中的大白猪和长白猪满足完全替换原则,使用时客户不用考虑猪的具体类型,就可以直接通过抽象的猪的接口来操作具体的大白猪和长白猪对象。

然后,我们修改喂猪机器人的代码,使其不考虑猪的类型,只应用抽象的猪的接口来操作所有猪的对象实例。例如,喂猪时喂猪机器人需要吼叫的不再是"大白猪,吃!"或"长白猪,吃!"而是"猪,吃!"这种通过抽象类或抽象接口来操作对象的方式就是"针用接口编程"的方法,而此前那种通过具体的类来操作对象的方法可以被称为"针对实现编程"的方法。
改进后的养猪场如图v3-1所示。

                  图v3-1

这个改进的养猪场会为我们带来什么好处呢?假设现在养猪场的老板需要引进波中猪,他只要买来几头波中猪的仔猪,扔进养猪场就可以了。喂猪机器人的代码不需要发生任何变化,它面对每一头猪只要说"猪,吃!"所有类型的猪都可以愉快地进食。不管养猪场饲养的猪有多少种,喂猪机器人都会把猪喂得腰肥体壮。
添加了波中猪后的系统结构如图v3-2所示。

                            图v3-2

可以看到,喂猪机器人完全是针对接口进行编程的,当系统添加一个新的类型时,只需要添加新类型的代码,而系统中原有的代码不需要做任何的改变就可以适应新的需求一一这完全符合开闭原则。

V3版面向对象养猪厂的实现代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9
 10 namespace PigFactoryV3
 11 {
 12     public partial class Form1 : Form
 13     {
 14         /*
 15          * 猪悟能的博客
 16          * http://www.cnblogs.com/hackpig/
 17          *
 18         建成后的养猪场生意兴隆, 老板决定进军国际市场, 但是为了迎合外国人口味, 引入了几条长白猪.
 19         因此,这里猪的类型成了变化点.
 20         我们把大白猪类, 改成猪接口, 这样喂猪机器人的工作变成了, "猪,吃", 而不是原来的 "大白猪,吃"
 21         即使老板再增加几头波中猪, 我们也不再需要修改喂猪机器人的工作()了. 只需要增加一个波中猪的类实现猪接口
 22
 23
 24         从这里我们可以总结出有关设计模式的第一个核心设计原则:
 25
 26         设计模式最根本的意图是适应需求变化, 我们应只对变化或者可能变化的部分使用设计模式,对于不变的部分滥用设计
 27         模式就会造成"过度设计"
 28
 29          */
 30
 31
 32         public Form1()
 33         {
 34             InitializeComponent();
 35
 36             feedPigRobot robot = new feedPigRobot("大润发养猪场");
 37             robot.Attack(new dbPig(1));
 38             robot.Attack(new dbPig(2));
 39             robot.Attack(new dbPig(3));
 40             robot.Attack(new dbPig(4));
 41             robot.Attack(new dbPig(5));
 42
 43             robot.Attack(new cbPig(6));
 44             robot.Attack(new cbPig(7));
 45             robot.Attack(new cbPig(8));
 46             robot.Attack(new cbPig(9));
 47             robot.Attack(new cbPig(10));
 48
 49             rtbMsginfo.Text = robot.work();
 50
 51         }
 52     }
 53
 54
 55     public abstract class feedPigFactory
 56     {
 57         private string _factoryName;
 58
 59         public string FactoryName
 60         {
 61             get { return _factoryName; }
 62             set { _factoryName = value; }
 63         }
 64
 65     }
 66
 67     public class feedPigRobot:feedPigFactory
 68     {
 69         IList<Ipig> pigList = new List<Ipig>();
 70
 71         public feedPigRobot(string factoryName)
 72         {
 73             base.FactoryName = factoryName;
 74         }
 75
 76         public void Attack(Ipig pig)
 77         {
 78             pigList.Add(pig);
 79         }
 80
 81         public string work()
 82         {
 83             string msgstr = string.Empty;
 84             foreach (Ipig m in pigList)
 85             {
 86                 msgstr += m.eat()+Environment.NewLine;
 87             }
 88
 89             return string.Format("{0}{1}{2}",
 90                 base.FactoryName + Environment.NewLine,
 91                 "喂猪机器人开始工作...." + Environment.NewLine + Environment.NewLine,
 92                 msgstr);
 93         }
 94     }
 95
 96
 97
 98     public interface Ipig
 99     {
100
101         int PigIndex
102         {
103             get;
104             set;
105         }
106
107         string eat();
108
109     }
110
111
112     public class cbPig : Ipig
113     {
114         private int _pigIndex;
115
116         public int PigIndex
117         {
118             get { return _pigIndex; }
119             set { _pigIndex = value; }
120         }
121         public cbPig(int pignum)
122         {
123             this._pigIndex = pignum;
124         }
125
126         public string eat()
127         {
128             return string.Format("{0}[{1}]开始吃.", "长白猪", _pigIndex);
129         }
130     }
131
132
133
134     public class dbPig :Ipig
135     {
136         private int _pigIndex;
137
138         public int PigIndex
139         {
140             get { return _pigIndex; }
141             set { _pigIndex = value; }
142         }
143         public dbPig(int pignum)
144         {
145             this._pigIndex = pignum;
146         }
147
148         public string eat()
149         {
150             return string.Format("{0}[{1}]开始吃.", "大白猪", _pigIndex);
151         }
152     }
153
154 }

运行结果如下:

代码分析:

(1) feedPigRobot是喂猪机器人类

其成员函数 Attack 的参数是Ipig, 它是猪的接口
  public void Attack(Ipig pig)
  这个参数可以接纳 dbPig , 大白猪类的实例, 或者是 cbPig,  长白猪类的实例.

work() 成员函数 遍历所有IPig的"猪"对象, 调用它的eat()方法. (完成对所有猪喂食的操作)

  foreach (Ipig m in pigList)
  {
        msgstr += m.eat()+Environment.NewLine;
  }

(2) 有了猪的抽象接口(Ipig), 它抽象出了猪共有了行为"吃", 即方法eat(). 喂猪机器人只对这个猪抽象接口喂食, 就不需要知道喂的究竟是长白猪,还是大白猪了.

养猪场的老板还曾经提到过养鸡和养青蛙。对此,我们必须明确该需求是否是合理的需求,系统是否需要适应这一需求变化。一般说来,养猪场是不会养鸡、养青蛙的,我们没必要为此多费心思。但如果老板故意刁难的话,我们也不是没有解决方案:适应这一需求变化的方法是提取出一个更一般的"动物接口"机器人完全使用"动物接口"类来操作所有的对象。

现在,面向对象的现代化养猪场又欣欣向荣地发展起来了。但我们不能放松警惕,变化的需求随时都会出现。例如这一次,养猪场的老板突然觉得,老从外面引进仔猪太亏,他希望能在养猪场内部建造一个繁殖基地,自产自销。于是,我们建造了二个猪工厂,最初的猪工厂结构如图V5-1所示。

图v5-1

不难发现,在实现猪工厂时,我们又陷入了针对实现编程的陷阱。管理员使用猪工厂来选择繁殖哪种类型的仔猪,猪工厂根据管理员的要求执行不同的繁殖过程,繁殖不同类型的仔猪。对于系统中己有的大白猪和长白猪,这没有问题,但是当我们想繁殖波中猪时,问题又产生了,猪工厂的代码必须修改。显然,我们必须想办法来隔离有关对象创建的代码,以适应需求变化。设计模式中的创建型模式恰恰可以满足我们的需要。

为了隔离具体的繁殖过程,我们可以定义一个猪工厂的抽象接U类,其派生类大自猪工厂和长白猪工厂具体地实现接口中的繁殖行为。这样,和具体实现相关的代码被推迟到了具体的派生类工厂中去实现,我们在系统外只要用不同的派生类工厂调用繁殖方法,就可以繁殖出不同的仔猪了。修改后的结构如图V6-1所示。
这一改进为我们带来的好处是,当我们要添加一种猪的类型时,也相应地添加繁殖这种猪的工厂,系统内原布的代码不需要改变。这时,猪工厂负责繁殖仔猪,然后把仔猪交给喂猪机器人,这些仔猪的生、老、病、死就完全由喂猪机器人来负责了。为了在这一结构中添加波中猪,我们需要做的事情有添加波中猪类、添加波中猪工厂类、修改管理员繁殖仔猪的代码等,这些工作都是在系统外完成的,与系统内原有的代码无关(如图V6-1所示)。

图v6-1

面向对象养猪厂V6版实现代码如下:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9
 10 namespace PigFactoryV6
 11 {
 12     public partial class Form1 : Form
 13     {
 14         /*
 15          * 猪悟能的博客
 16          * http://www.cnblogs.com/hackpig/
 17          *
 18         突然有一天,老板觉得从外面进猪仔太亏, 他希望在养猪场内部建立一个繁殖基地, 自产自销.
 19         于是, 软件团队建立了一个猪工厂.
 20
 21         现在, 养猪场完全可以由自产的仔猪开始喂养了.
 22         无论是增加要喂食猪的品种, 还是繁殖新的猪的品种, 我们现在都不用改动原有的代码.
 23         只需要增加新的猪品种的类, 实现猪工厂接口, 和猪接口就可以了.
 24
 25         由些我们总结出设计模式第二个核心设计原则:
 26
 27         尽量针对接口编程, 而不要针对实现编程. 针对接口编程的组件不需要知道对象的具体
 28         类型和实现, 只需要知道抽象类定义了哪些接口, 这减少了实现上的依赖关系.
 29
 30          */
 31
 32         public Form1()
 33         {
 34             InitializeComponent();
 35
 36             feedPigRobot robot1 = new feedPigRobot("大润发养猪场");
 37             adminMan man1=new adminMan(2);
 38             foreach (Ipig m in man1.Piglist)
 39                 robot1.Attack(m);
 40             this.rtbMsgInfo.Text = robot1.work();
 41
 42         }
 43     }
 44
 45
 46     public class adminMan
 47     {
 48         private IList<Ipig> _piglist;
 49
 50         public IList<Ipig> Piglist
 51         {
 52             get { return _piglist; }
 53             set { _piglist = value; }
 54         }
 55
 56         public adminMan(int breedType)
 57         {
 58             IList<Ipig> piglist1 = new List<Ipig>();
 59             switch (breedType)
 60             {
 61                 case 1:  //大白猪
 62                     foreach (Ipig m in new breedDBpig().breedPig())
 63                         piglist1.Add(m);
 64                     break;
 65                 case 2:  //长白猪
 66                     foreach (Ipig m in new breedCBpig().breedPig())
 67                         piglist1.Add(m);
 68                     break;
 69                 default:
 70                     break;
 71             }
 72             if (piglist1.Count > 0)
 73                 _piglist = piglist1;
 74
 75         }
 76     }
 77
 78
 79
 80     public interface IbreedPig
 81     {
 82         IList<Ipig> breedPig();
 83     }
 84
 85     public class breedDBpig : IbreedPig
 86     {
 87         private IList<Ipig> pigList = new List<Ipig>();
 88         public IList<Ipig> breedPig()
 89         {
 90             Random ran = new Random(DateTime.Now.Millisecond);
 91             for (int i = 0; i < ran.Next(2, 20); i++)
 92                 pigList.Add(new dbPig(i));
 93             return pigList;
 94         }
 95     }
 96
 97     public class breedCBpig : IbreedPig
 98     {
 99         private IList<Ipig> pigList = new List<Ipig>();
100         public IList<Ipig> breedPig()
101         {
102             Random ran = new Random(DateTime.Now.Millisecond);
103             for (int i = 0; i < ran.Next(2, 20); i++)
104                 pigList.Add(new cbPig(i));
105             return pigList;
106         }
107     }
108
109
110     public abstract class feedPigFactory
111     {
112         private string _factoryName;
113
114         public string FactoryName
115         {
116             get { return _factoryName; }
117             set { _factoryName = value; }
118         }
119
120     }
121
122     public class feedPigRobot : feedPigFactory
123     {
124         IList<Ipig> pigList = new List<Ipig>();
125
126         public feedPigRobot(string factoryName)
127         {
128             base.FactoryName = factoryName;
129         }
130
131         public void Attack(Ipig pig)
132         {
133             pigList.Add(pig);
134         }
135
136         public string work()
137         {
138             string msgstr = string.Empty;
139             foreach (Ipig m in pigList)
140             {
141                 msgstr += m.eat() + Environment.NewLine;
142             }
143
144             return string.Format("{0}{1}{2}",
145                 base.FactoryName + Environment.NewLine,
146                 "喂猪机器人开始工作...." + Environment.NewLine + Environment.NewLine,
147                 msgstr);
148         }
149     }
150
151
152
153     public interface Ipig
154     {
155
156         int PigIndex
157         {
158             get;
159             set;
160         }
161
162         string eat();
163
164     }
165
166
167     public class cbPig : Ipig
168     {
169         private int _pigIndex;
170
171         public int PigIndex
172         {
173             get { return _pigIndex; }
174             set { _pigIndex = value; }
175         }
176         public cbPig(int pignum)
177         {
178             this._pigIndex = pignum;
179         }
180
181         public string eat()
182         {
183             return string.Format("{0}[{1}]开始吃.", "长白猪", _pigIndex);
184         }
185     }
186
187
188
189     public class dbPig : Ipig
190     {
191         private int _pigIndex;
192
193         public int PigIndex
194         {
195             get { return _pigIndex; }
196             set { _pigIndex = value; }
197         }
198         public dbPig(int pignum)
199         {
200             this._pigIndex = pignum;
201         }
202
203         public string eat()
204         {
205             return string.Format("{0}[{1}]开始吃.", "大白猪", _pigIndex);
206         }
207     }
208
209
210 }

运行效果:

代码说明:

(1)  下面代码可以看到,

feedPigRobot是喂猪机器人类, adminMan是繁殖管理类, 它使用工厂方式创建对应品种的猪.


 feedPigRobot robot1 = new feedPigRobot("大润发养猪场");
            adminMan man1=new adminMan(2);
            foreach (Ipig m in man1.Piglist)
                robot1.Attack(m);
            this.rtbMsgInfo.Text = robot1.work();
adminMan()有个构造函数参数, 传入参数1,或者2, 表示使用工厂方式创建随机数量的大白猪或者是长白猪.
 IList<Ipig> piglist1 = new List<Ipig>();
            switch (breedType)
            {
                case 1:  //大白猪
                    foreach (Ipig m in new breedDBpig().breedPig())
                        piglist1.Add(m);
                    break;
                case 2:  //长白猪
                    foreach (Ipig m in new breedCBpig().breedPig())
                        piglist1.Add(m);
                    break;
                default:
                    break;
            }

(2)  本例程传入adminMan()参数为2, 因此只是随机创建了一批长白猪

由此,我们可以总结出设计模式的第二个核心设计原则:
尽量针对接口编程,而不要针对实现编程。针对接口编程的组件不需要知道对象的具体类型和实现,只需要知道抽象类定义了哪些接口,这减少了实现上的依赖关系。

未完待续......

时间: 2024-08-03 11:59:42

设计模式之 面向对象的养猪厂的故事,C#演示(一)的相关文章

设计模式之 面向对象的养猪厂的故事,C#演示(二)

(三) 优先使用聚合,而不是继承 有一段时间,养猪场的老板雇用了清洁工人来打扫猪舍.但有一天,老板忽然对自己说"不对啊,既然我有机器人,为什么还要雇人来做这件事情?应该让机器人来打扫宿舍!" 于是,这个需求被提交到了机器人的研发小组.看到这个需求,我们敏感地意识到,这是一个潜藏了更多变化的需求,未来机器人的功能还可能会不断增加,于是,我们提取出了一个抽象的机器人接口,并实现了两个具体的机器人类一-喂猪机器人和清洁机器人.系统的结构如图V8-1所示. 图V8-1 这样一来,老板希望机器人

【设计模式】面向对象基础

最近一直在学习<大话设计模式>根据师傅对我的指导,让我先学习这本书的附录--面向对象基础.说实在话,面向对象技术从很早就接触了,从刚开始的C++,其次是软工视频,然后是UML,紧接着是C#,直到现在的设计模式.. 总的来说,在设计模式之前,我对面向对象的了解还只是停留在封装.继承.多态的层次上,虽然在C#视频中,有全面的讲解了一下,但是自己还是晕晕乎乎的,脑子中还是有很多疑云..直到这次的设计模式,通过通过幽默生动.而又通俗易懂的故事,对面向对象技术深入浅出,我才算是真正的入门了.. 这篇博客

【小话设计模式】面向对象设计原则

1.单一职责原则 单一职责原则的核心思想就是:系统中的每一个对象都应该只有一个单独的职责,而所有对象所关注的就是自身职责的完成.英文缩写SRP  Single Responsibility Principle 单一职责原则-->"高内聚,低耦合",每个类应该只有一个职责,此外只能提供一种功能,而引起类变化的原因应该只有一个.在设计模式中,所有的设计模式都遵循这一原则. 优点: 可以降低类的复杂度: 提高类的可读性,提高系统的可维护性: 变更引起的风险降低. 2.里氏替换原则 里氏

【设计模式】面向对象小结——重写与重载

通过对<大话设计模式>附录的学习,让我对面向对象技术有了更深一层的理解!下面是我画的一张导图,是我对面向对象技术的总体概括.这篇文章的主要内容,就是围绕这张图,来讲述我的理解.. 由图得知,我将面向对象分为三个部分:基本.特点及其功能.它们之间像是一种层层递进的关系. 如果没有基本的抽象思想,将具有相同属性和功能的对象进行整合,那么也就没有面向对象技术,更不可能产生面向对象特点.所以,抽象是核心,是基本:如果没有封装.继承和多态,那么类与类.对象与对象.类与对象之间,就没有了联系,就不能实现对

跟我学设计模式视频教程——面向对象理论,模板方法

课程视频 模板方法 面向对象理论 唠嗑 课程笔记 课程笔记 课程代码 课程代码 新课程火热报名中 课程介绍 跟我学设计模式视频教程--面向对象理论,模板方法

设计模式2 面向对象设计原则

面向对象设计原则  原则的目的 面向对象设计原创表  单一职责原则案例 开闭原则 案例 依赖倒转原则 案例 面向对象设计原则  对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一.在面向对象设计中,可维护性的复用是以设计原则为基础的.每一个原则都蕴含一些面向对象设计的思想,可以从不同的角度提升一个软件结构的设计水平.  面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含

【设计模式】面向对象小结——接口、泛型和委托

上一篇文章,通过一张概括性导图,总结性的讲解了一下我对面向对象的理解,以及重写与重载的区别. 这篇文章的主要内容是写,我对面向对象功能:接口.泛型和委托的理解..很多人都认为,我不使用它们,照样能实现程序想要的功能,为什么还要用它们?可以这么说,如果要想混IT行业,那么,我们就要成为专业人员.那么,我们所写的代码就不仅仅是实现其功能那么简单了,我们还要提高程序的性能,更重要的是,我们所写的代码是给别人看的,要让别人看得懂,实现团队合作..接口.泛型和委托让我们的代码更结构化.专业化..    

Java设计模式之——面向对象六大原则

面向对象六大原则: 设计模式六大原则(1):单一职责原则 设计模式六大原则(2):开闭原则 设计模式六大原则(3):里氏替换原则 设计模式六大原则(4):依赖倒置原则 设计模式六大原则(5):接口隔离原则 设计模式六大原则(6):迪米特原则 设计模式六大原则(1):单一职责原则 单一职责原则的英文名称是 Single Responsibility Principle,缩写为 SRP.SRP 的定义是:就一个类而言,应该仅有一个引起它变化的原因.简单来说,一个类中应该是一组相关性很高的函数.数据的

java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设计原则 单一职责原则 开闭原则 里氏替换原则 依赖注入原则 接口分离原则 迪米特原则 单一职责原则 其实就是开发人员经常说的"高内聚,低耦合" 也就是说,每个类应该只有一个职责,对外只能提供一种功能,而引起类变化的原因应该只有一个.在设计模式中,所有的设计模式都遵循这一原则. 开闭原则 核