设计模式读书笔记之简单工厂

    ---每一模式的出现都是为了解决某一种或某一类问题,或者对某种对象间的耦合关系进行解耦合,使紧耦合变成松耦合的关系。
1.前言(解耦过程)
 当我们还是一个刚刚入门或者刚刚接触面向对象程序员或者学习者的时候。我们会很习惯的用类来描述某一中具有相同属性的东西。
 如苹果。而且它有名字、皮等属性。然后我们就会定义一个苹果(Apple): 

View Code
 1 public class Apple
2 {
3 public string Name{get;set;}
4 public Color Skin{get;set;}
5
6 public void Display()
7 {
8 Console.Write("我是苹果");
9 }
10 }

 然后我们想得到一个苹果的时候,我们就很习惯得去做一件事件,代码和结构图如下:

View Code
1 Apple apple = new Apple {Name="苹果",Skin="Green"}

 紧耦合结构图:

                         图1-1

 然后有些人就会想到 我们既然学了苹果类,苹果可以这样写,那香蕉、葡萄等。代码如下:
 

View Code
 1 public class Banana
2 {
3 public string Name{get;set;}
4 public string Skin{get;set;}
5
6 public void Display()
7 {
8 Console.Write("我是香蕉");
9 }
10 }
11
12 public class Grape
13 {
14 public string Name{get;set;}
15 public string Skin{get;set;}
16
17 public void Display()
18 {
19 Console.Write("我是葡萄");
20 }
21 }

  多个紧耦合结构图:

                          图1-2

 当自己慢慢对OO熟悉后 发现这样代码不好,所以稍作改善,应该采用接口或者抽象类来实现(多态)。
 所以定义了一个水果的接口,然后所有的水果的继承它。代码如下:
 

View Code
1 public Interface IFruit
2 {
3 public void Display();
4 }

 

 然后代码中就出现大量如下代码:
 

View Code
 1 IFruit fruit;
2 if(fruitType.Equal("Apple"))
3 {
4 fruit = new Apple{Name="苹果",Skin="Green"};
5 }else if(fruitType.Equal("Banana"))
6 {
7 fruit = new Banana{Name="香蕉",Skin="Yellow"};
8 }else if(fruitType.Equal("Grape"))
9 {
10 fruit = new Grape{Name="葡萄",Skin="Grape"};
11 }

 使用了接口结构图:

 

                      图1-3

 这样如果我以后增加了一个新类型的水果的话,要修改多处的逻辑代码。这样导致出现一个代码维护困难的问题。
 结果就想到用一个果园(Orchard)来解决此问题,果园可以为我们提供水果。代码如下:
 

View Code
 1 public class OrchardFactory
2 {
3 public IFruit ProvideFruit(string fruitType)
4 {
5 if(fruitType.Equal("Apple"))
6 {
7 return new Apple{Name="苹果",Skin="Green"};
8 }else if(fruitType.Equal("Banana"))
9 {
10 return new Banana{Name="香蕉",Skin="Yellow"};
11 }else if(fruitType.Equal("Grape"))
12 {
13 return new Grape{Name="葡萄",Skin="Grape"};
14 }
15 }
16 }
17

  

这样就解决了上面多出修改代码的问题了,但同时也引进了一个新问题,就是每次都要传进一个参数,而且提供水果的方法
又每次都需要进行逻辑判断,单水果种类多的话,在性能上有一定的影响,所以对果园进行了一些修改。代码如下: 
 

View Code
 1 public class OrchardFactory
2 {
3 public IFruit ProvideApple()
4 {
5 return new Apple{Name="苹果",Skin="Green"};
6 }
7 public IFruit ProvideBanana()
8 {
9 return new Banana{Name="香蕉",Skin="Yellow"};
10 }
11 public IFruit ProvideGrape()
12 {
13 return new Grape{Name="葡萄",Skin="Grape"};
14 }
15 }
16

 简单工厂结构图:

                        图1-4

 这样就引出了一个设计模式“简单工厂”。


2.概要
 什么是简单工厂:其实简单工厂严格来说它并不是一种设计模式,更偏向于一种编程习惯。
 简单工厂是一种创建型模式,主要为客户(这里客户不是指人,而是指程序的中对象的请求者)提供客户所需的具有相同父类或者相同接口的不同产品(这里可以认为是同一产品族)。


3.结构图分析:
 图1-1产品完全跟客户端耦合。客户必须知道具体的产品是如何创建。
 图1-2多种产品与客户端耦合这样客户端必须去记得每一种产品。
 图1-3水果接口与客户端耦合,客户端不需要知道有什么产品。但有一个不好的地方就是客户端会多处出现重复代码。
 图1-4简单工厂完整图,水果接口跟工厂耦合,客户跟工厂耦合,这样使得客户跟具体产品之间完全解耦,而工厂跟具体产品间变成送耦合关系。

 

4.静态工厂:
 如果为简单工厂的方法加一个静态变量的关键字,此工厂就称为静态工厂。
 优点:方便使用,不用动态去实例化工厂就可以创建产品。
 缺点:因为static关键字支持继承。但子类(派生类)拥有父类(基类)的静态属性同一个值(也可以理解为同一个引用型变量)。


5.目的:
 简单工厂的目的在于解决客户于对象间的直接依赖的关系,把他们之间的紧耦合进行解耦。
 从代码的角度来看,主要问题解决重复造轮子的问题,也就是说在代码中多处重复出现相同代码,导致代码越来越难以维护的问题。
 实现了用复用代替Copy代码。


6.使用场合:
 从抽象角度来看:适用于满足产品请求者、产品提供者、提供相同父类或接口的不同产品(同一产品族)。如果存在以上关系就
 可以用简单工厂。
 从实际应用来看:适用于如数据库创建连接池,也可以和其他设计模式一起适用。

7.附加代码:点击下载

原文地址:https://www.cnblogs.com/smlAnt/p/2112293.html