工厂方法定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
看这么罗嗦,其实就是多态,父类申明,子类构造。
为什么会有工厂方法?
我们在写代码的时候经常的使用new关键字,也就是实例化一个具体类,绑着的是具体实现,那么这样会带来一个后果,在今后的变更中,我们不得不去修改那个类,这将
导致代码的不稳定,我们还得去测试一切和这个类有关系的代码,并且我们违反了一个很重要的原则:对修改关闭原则。
我们需要将new和客户端代码分离开来
我们要做个人才网
// 技能页
class SkillsPage
{
//省略1000,下面同此
}
// 教育页
class EducationPage
{
}
// 经验页
class ExperiencePage
{
}
//介绍页
class IntroductionPage
{
}
// 结果页
class ResultsPage
{
}
// 结论页
class ConclusionPage
{
}
// 总结页
class SummaryPage
{
}
// 文献页
class BibliographyPage
{
}
有了这一个一个的模块,我们可以接下去做具体的页面了。
1 public class createResume
2 {
3 //试想一下我现在创建一个个人简历页面,包含了教育背景,经验,技能
4 //我创建了一个类,用来做个人简历页面的创建
5 SkillsPage skill;
6 EducationPage educ;
7 ExperiencePage exp;
8
9
10 public createResume()
11 {
12
13 skill = new SkillsPage();
14
15 educ = new EducationPage();
16
17 exp = new ExperiencePage();
18 }
19
20 //展示个人简历页面
21 public void display()
22 {
23 Console.WriteLine(skill);
24 Console.WriteLine(educ);
25 Console.WriteLine(exp );
26 }
27 }
28
29
30 //我又要做个报告页面,包含了介绍,结果,结论,总结,文献
31 public class createReport
32 {
33 IntroductionPage intro;
34 ResultsPage result;
35 ConclusionPage conclusion;
36 SummaryPage summary;
37 BibliographyPage bibliography;
38
39 public createReport()
40 {
41 intro = new IntroductionPage();
42 result = new ResultsPage();
43 conclusion = new ConclusionPage();
44 summary = new SummaryPage();
45 bibliography = new BibliographyPage();
46 }
47
48 //展示报告页面
49 public void display()
50 {
51 Console.WriteLine(intro);
52 Console.WriteLine(result);
53 Console.WriteLine(conclusion);
54 Console.WriteLine(summary);
55 Console.WriteLine(bibliography);
56 }
57 }
58
不错不错,那么再做个首页,搜索页,注册页,登陆页..........饿,苦逼的码农我好累,不想写了,“不想写滚蛋!”...
如果我们换成下面这样。
//比对一下,可以发现者其中很多地方代码是相通的比如这些页面有没什么共通点,可以把不变动的提炼出来
//页面基类
abstract class Page
{
//共通的
protected void common()
{
//省略500
}
}
//通过分离我们可以少写很多代码
// 技能页
class SkillsPage : Page
{
//少写500行啊,以下同此
}
// 教育页
class EducationPage : Page
{
}
// 经验页
class ExperiencePage : Page
{
}
//介绍页
class IntroductionPage : Page
{
}
// 结果页
class ResultsPage : Page
{
}
// 结论页
class ConclusionPage : Page
{
}
// 总结页
class SummaryPage : Page
{
}
// 文献页
class BibliographyPage : Page
{
}
哇塞,少写了N*500行代码啊,偷笑..还有哪可以少写点呢
//我们再把创建页面的代码提炼出来
//页面抽象类
abstract class Document
{
//页面包含子模块
public List<Page> Pages { get; private set; }
public Document()
{
this.CreatePages();
}
// 创建具体页面
abstract private void CreatePages();
//展示页面
public void Display()
{
Console.WriteLine(this);
for (int i = 0; i < Pages.Count; i++)
{
Console.WriteLine(" " + Pages[i].ToString());
}
}
//共通
public void Common()
{
//省略500,苦逼的程序员又偷笑....
}
}
在看看老板要我们添加的页面成啥样了
1 //具体页面类-个人简历,包括技能,教育,经验
2 class Resume : Document
3 {
4
5 //创建页面实现
6 override private void CreatePages()
7 {
8 Pages = new ArrayList();
9 Pages.Add(new SkillsPage());
10 Pages.Add(new EducationPage());
11 Pages.Add(new ExperiencePage());
12
13 }
14 }
15
16 //具体产品类-报告,包括介绍,结果,结论,总结,文献
17 class Report : Document
18 {
19 //创建产品实现
20 override public void CreatePages()
21 {
22 Pages = new ArrayList();
23 Pages.Add(new IntroductionPage());
24 Pages.Add(new ResultsPage());
25 Pages.Add(new ConclusionPage());
26 Pages.Add(new SummaryPage());
27 Pages.Add(new BibliographyPage());
28
29 }
30 }
看着很舒心,根据不同需要,我们重写了创建页面的代码,以后就不怕老板要求多了,我只要继承下,重写个创建方法,最多再添点功能么
看看客户端调用,再想想工厂方法的定义
1 static void Main(string[] args)
2 {
3 //个人简历
4 Document resume = new Resume();
5 resume.Display();
6
7 //报告
8 Document report = new Report();
9 report.Display();
10
11 Console.Read();
12
13 }
等等,这里为啥还是有new?可以这样理解,Resume和Report是2个生产页面的工厂,他们都有createPage的加工程序,以及展示产品的方法,我们说把客户端代码和
new分离开来,是分离的具体实现,那么上面的代码的具体实现在哪呢,在一个一个的子模块里:技能页,教育页...等等。
也许我们的个人简历页面的技能页要修改或者删除,那么我们只需修改工厂里的加工程序,咦,不是说我们要对修改关闭么,真的都死板的去遵循原则,那代码别想写了,
我们只能尽力的去靠近原则,灵活运用,不是死板遵循。new 具体实现,肯定存在的,只是工厂把他们圈起来了,方便我们取用。
任性过,颓废过,荒唐过,现在还是好好的向前走吧,别再徘徊路边