今天分享设计模式中最简单的一种模式 简单工厂模式。先从面向对象说起,面向对象有三大特性:继承,封装,多态。
所谓封装:在面向对象语言中,我们都是以类来组织代码,类中定义了属性和方法,我们在调用的时候只需要去使用对象的方法名或者属性名就可以了,而不必甚至不需要知道方法的具体实现,类比生活中的例子,榨汁机。我们只知道用它可以榨果汁,放个苹果给我们一杯苹果汁,放个桔子给我们一杯桔子汁就可以了。我们不必要去关心 榨汁机是怎么去工作的。
所谓继承:就是子类继承了父类,父类所有的非私有的方法和属性,子类都可以拿来直接使用。就好比生活中,父亲给儿子留了一笔遗产。你可以直接使用这笔钱而不需要去创造这笔钱然后在去使用。
所谓多态:一个类可以有多个子类,而每个子类只能由一个父类,就好比。一个父亲可以有多个儿子,而每个儿子只可以有一个父亲。对于多态我们有2种理解。第一种是不同的人对同一件事所做的不同反应,例如 工作,对于农民来说就是种地,科学家 搞科研,工人 上班,学生 做作业。第二种是同一个人 在不同情况下,具有不同的身份和角色,例如 同样是你,在公司你可能是员工,在家里 你是你父母的儿子,在路上你是行人。
先来看一个简单的例子:
我们首先定义一个父类Person类:
/// <summary>
/// 定义父类Person
/// </summary>
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
/// <summary>
/// 自我介绍
/// </summary>
public void SayHi()
{
Console.WriteLine("大家好我是" + Name + ",我今年" + Age + "岁了!");
}
}
定义2个子类,一个Student类,一个Teacher类
public class Student : Person
{
}
public class Teacher: Person
{
}
在控制台中访问:
static void Main(string[] args)
{
Student s = new Student();
s.Name = "张三";
s.Age = 20;
s.SayHi();
}
输出:
可以看出子类是可以使用父类的非私有的属性和方法。
当然 老师的自我介绍和学生自我介绍肯定不一样。如果我们要实现 老师的自我介绍是 大家好。我是XX老师,我今年工作几年了。 学生的自我介绍是大家好。我是某某学生,我今年多少岁了,应该怎么做呢。
如下图:
编译器会有警告,因为我们在基类中已经使用了SayHi方法来做自我介绍。为了能更好的解决问题。我们就要用到多态了。
我们把基类Person类改写成抽象类,把基类中的SayHi方法改写成抽象方法。
直接上图:
/// 定义父类Person
/// </summary>
public abstract class Person
{
public string Name { get; set; }
public int Age { get; set; }
/// <summary>
/// 自我介绍
/// </summary>
//public void SayHi()
//{
// Console.WriteLine("大家好我是" + Name + ",我今年" + Age + "岁了!");
//}
/// <summary>
/// 抽象方法,自我介绍
/// 抽象方法没有具体实现,只能通过子类覆写来实现。
/// </summary>
public abstract void SayHi();
}
子类
public class Teacher : Person
{
public int YearOfWork { get; set; }
public override void SayHi()
{
Console.WriteLine("大家好我是" + Name + "老师,我工作" + YearOfWork + "年了!");
}
}
public class Student : Person
{
/// <summary>
/// 重写基类自我介绍方法
/// </summary>
public override void SayHi()
{
Console.WriteLine("大家好我是" + Name + ",我今年" + Age + "岁了!");
}
}
在Main方法中 定义如下
static void Main(string[] args)
{
Teacher t = new Teacher();
t.Name = "AAA";
t.YearOfWork = 5;
t.SayHi();
Person p = new Teacher() { Age = 18, Name = "李四", YearOfWork = 5 };
p.SayHi();
}
输出结果
如上图 我们可以看到 p 和t 都是调用的teacher类中的sayhi方法。 这就是多态。子类通过覆写 父类中的抽象方法或者虚方法来实现。
这个也叫里氏替换原则 就是凡是父类出现的地方子类都可以出现。 试想一下 如果 Person类不定义为抽象类。以上2个输出结果会有什么不同。
简单工厂正是 基于以上原则来实现的。
以上是对面向对象的一个简单回顾。下面我们来讲 简单工厂设计模式。设计模式不是一种新的技术,只是在编写代码中一些好的方式的积累和经验的积累。
从上图 我们可以看出:
从结构可以看出,工厂依赖于所有的子类产品,客户只需知道父类产品和工厂即可。工厂是整个模式的核心,以不变应万变。
在现实生活中 我们知道。工厂是用来生产产品的。在面向对象的技术里面工厂也是用来生产产品的。在这里我们的工厂是用来给类生产对象的。
在前面我们简单介绍过封装 继承 多态。那么在使用简单工厂模式的时候我们首先要定义好角色。父类 ,子类 和工厂类。 子类继承父类。 父类定义子类要实现的方法。工厂 创建类的对象。客户调用的时候只需要 知道工厂类和父类就可以了。上图红线标注。
我们以生活中的例子来说明。
首先我们创建一个父类 。我们知道车有很多。什么宝马 奔驰。等等。我们先定义一个父类 。小汽车类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Demo
{
/// <summary>
/// 父类
/// </summary>
public abstract class Car
{
public abstract void Run();
}
}
在来定义2个子类 ,子类继承父类
一个是宝马汽车类:
/// <summary>
/// 子类1
/// </summary>
public class BMWCar:Car
{
public override void Run()
{
Console.WriteLine("宝马轿车在行驶!");
}
}
/// <summary>
/// 子类2
/// </summary>
public class BenzCar:Car
{
public override void Run()
{
Console.WriteLine("奔驰轿车在行驶!");
}
}
在来定义一个工厂类
/// <summary>
/// 工厂
/// </summary>
public class Factory
{
public static Car CreateCar(string carType)
{
Car car = null;
switch (carType)
{
case "BMW":
car = new BMWCar();
break;
case "Benz":
car = new BenzCar();
break;
}
return car;
}
}
在工厂类中。我们定义了一来Create方法。用来创建对象。通过父类对象来返回我们创建的对象。
在Main方法 中调用 就是上图中的客户端。我们只需要关注父类和工厂 。
Car car = Factory.CreateCar("Benz");
car.Run();
运行结果 就是 :奔驰汽车在行驶。