单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
解释:保证一个类只有一个实例的一种实现方法,为了降低对象之间的耦合度。它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个实例的数量只有一个,也就是说,单例模式就是保证在整个应用程序周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获得该实例的全局访问点。
Public class Singleton
{
//私有变量来记录Singleton的唯一实例
private static Singleton instance;
//私有构造函数
Private Singleton()
{}
//定义公有方法来提供该类的唯一全局访问点
Public static Singleton GetInstance()
{
//如实例不存在,则New一个新的实例,否则返回已有实例
if(instance==null)
{
instance =new Singleton();
}
return instance;
}
}
Singleton类通过定义一个私有变量instance来记录单例类的唯一实例,私有方法Singleton()来防止外界使用new关键字类创建该类实例。公有方法GetInstance()来提供该类实例的唯一全局访问点。
多线程时的单例
public class Singleton
{
// 定义一个静态变量来保存类的实例
private static Singleton instance;
// 定义一个标识确保线程同步
private static readonly object locker = new object();
// 定义私有构造函数,使外界不能创建该类实例
private Singleton()
{
}
// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
public static Singleton GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (instance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
—————————————————————————————————————————————————————
工厂方法模式(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其他子类。
解释:工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创阿金推迟到子类中, 此时工厂类不再负责所有产品的创建,而是给出具体工厂必须实现的接口,这样工厂方法模式就可以允许系统不修改工厂类逻辑的前提下类添加新产品。
// 菜抽象类
public abstract class Food
{
// 输出点了什么菜
public abstract void Print();
}
// 西红柿炒鸡蛋这道菜
public class TomatoScrambledEggs : Food
{
public override void Print()
{
Console.WriteLine("西红柿炒蛋好了!");
}
}
// 土豆肉丝这道菜
public class ShreddedPorkWithPotatoes : Food
{
public override void Print()
{
Console.WriteLine("土豆肉丝好了");
}
}
// 抽象工厂类
public abstract class Creator
{
// 工厂方法
public abstract Food CreateFoddFactory();
}
// 西红柿炒蛋工厂类
public class TomatoScrambledEggsFactory:Creator
{
// 负责创建西红柿炒蛋这道菜
public override Food CreateFoddFactory()
{
return new TomatoScrambledEggs();
}
}
// 土豆肉丝工厂类
public class ShreddedPorkWithPotatoesFactory:Creator
{
// 负责创建土豆肉丝这道菜
public override Food CreateFoddFactory()
{
return new ShreddedPorkWithPotatoes();
}
}
// 客户端调用
class Client
{
static void Main(string[] args)
{
// 初始化做菜的两个工厂()
Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory();
Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory();
// 开始做西红柿炒蛋
Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoddFactory();
tomatoScrambleEggs.Print();
//开始做土豆肉丝
Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoddFactory();
shreddedPorkWithPotatoes.Print();
Console.Read();
}
}
—————————————————————————————————————————————————————
抽象工厂模式(Abstract Factory)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
解释:在现实生活中,一个工厂只创建单个产品这样的类很少(工厂方法),因为现在的工厂都多元化了。一个工厂创建一系列的产品。抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展。
//抽象产品
interface AbstractTV//所有电视的父类
{
void DIsplay();//显示电视类型
}
interface AbstractBX//所有冰箱的父类
{
void DIsplay();//显示冰箱类型
}
//具体产品
class HaiErTV:AbstractTV//海尔电视
{
public void DisPlay()
{
Console.WriteLine("我是海尔电视!");
}
}
class HaiXinTV:AbstractTV//海信电视
{
public void DisPlay()
{
Console.WriteLine("我是海信电视!");
}
}
class HaiErBX:AbstractBX//海尔冰箱
{
public void Display()
{
Console.WriteLine("我是海尔冰箱!");
}
}
class HaiXinBX:AbstractBX//海信冰箱
{
public void Display()
{
Console.WriteLine("我是海信冰箱!");
}
}
//抽象工厂
interface AbstractFactory//所有工厂的父类
{
AbstractBX CreateBX();//创建冰箱
AbstractTV CreateTV();//创建电视
}
//具体的工厂
class HaiErFactory:AbstractFactory//海尔工厂
{
public AbstractBX CreateBX()//创建海尔冰箱
{
return new HaiErBX();
}
public AbstractTV CreateTV()//创建海尔电视
{
return new HaiErTV();
}
}
class HaiXinFactory:AbstractFactory//海信工厂
{
public AbstractBX CreateBX()//创建海信冰箱
{
return new HaiXinBX();
}
public AbstractTV CreateTV()//创建海信电视
{
return new HaiXinTV();
}
}
//客户端
static void Main(string[] args)
{
AbstractBX bx;
//从配置文件中获取工厂名
string factoryName = ConfigurationManager.AppSettings["factory"];
//通过反射动态加载程序集,创建工厂实例
AbstractFactory factory = (AbstractFactory)Assembly.Load("抽象工厂模式").CreateInstance(factoryName);
bx = factory.CreateBX();
bx.Display();
Console.ReadLine();
}
//配置文件的代码
<appSettings>
<add key="factory" value="抽象工厂模式.MeiDiFactory"/>
</appSettings>
优点:抽象工厂在增加产品族的时候,很多好的符合了开闭原则。因为只需要增加具体产品和一个对象的具体工厂即可。不需要修改源代码。可以提供一个可视化界面,允许用户修改配置文件来修改工厂。
缺点:如果要增加一个产品等级结构,就需要修改几乎所有的代码。在上面的代码中说到了电视,冰箱。如果现在要增加一个抽象空调——海尔空调,海信空调,美的 空调。就需要在抽象工厂中新增创建空调的方法,在所有的具体工厂中实现该方法,如果你系统中工厂类过多,显然会给修改带来很大的麻烦。这严重违背了开闭原则。也是抽象工厂最大的缺点所在。所以抽象工厂的使用一定要谨慎。以免给后期维护带来诸多麻烦。
—————————————————————————————————————————————————————
建造者模式(Builder)
将一个复杂对象的结构与它的表示分离,使得同样的构建过程可以创建不同的表示。
解释:
在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:手机由主板,各种芯片,RAM 和ROM 摄像头之类的东西组成。拿手机来说,组装流水线是固定的、不变的,但是把不同的主板和其他组件组装在一起就会生产出不同型号的手机。在软件系统中我们也会遇到类似的复杂对象,并且这个复杂对象的各个部分按照一定的算法组合在一起,此时该对象的创建工作就可以使用建造者模式了。
// 客户类
class Customer
{
static void Main(string[] args)
{
// 客户找到电脑城老板说要买电脑,这里要装两台电脑
// 创建指挥者和构造者
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
// 老板叫员工去组装第一台电脑
director.Construct(b1);
// 组装完,组装人员搬来组装好的电脑
Computer computer1 = b1.GetComputer();
computer1.Show();
// 老板叫员工去组装第二台电脑
director.Construct(b2);
Computer computer2 = b2.GetComputer();
computer2.Show();
Console.Read();
}
}
// 指挥创建过程类
public class Director
{
// 组装电脑
public void Construct(Builder builder)
{
builder.BuildPartCPU();
builder.BuildPartMainBoard();
}
}
// 电脑类
public class Computer
{
// 电脑组件集合
private IList<string> parts = new List<string>();
// 把单个组件添加到电脑组件集合中
public void Add(string part)
{
parts.Add(part);
}
public void Show()
{
Console.WriteLine("电脑开始在组装.......");
foreach (string part in parts)
{
Console.WriteLine("组件"+part+"已装好");
}
Console.WriteLine("电脑组装好了");
}
}
// 抽象建造者,这个场景下为 "组装人" ,这里也可以定义为接口
public abstract class Builder
{
// 装CPU
public abstract void BuildPartCPU();
// 装主板
public abstract void BuildPartMainBoard();
// 当然还有装硬盘,电源等组件,这里省略
// 获得组装好的电脑
public abstract Computer GetComputer();
}
// 具体创建者,具体的某个人为具体创建者,例如:装机小王啊
public class ConcreteBuilder1 : Builder
{
Computer computer = new Computer();
public override void BuildPartCPU()
{
computer.Add("CPU1");
}
public override void BuildPartMainBoard()
{
computer.Add("Main board1");
}
public override Computer GetComputer()
{
return computer;
}
}
// 具体创建者,具体的某个人为具体创建者,例如:装机小李啊
// 又装另一台电脑了
public class ConcreteBuilder2 : Builder
{
Computer computer = new Computer();
public override void BuildPartCPU()
{
computer.Add("CPU2");
}
public override void BuildPartMainBoard()
{
computer.Add("Main board2");
}
public override Computer GetComputer()
{
return computer;
}
}
—————————————————————————————————————————————————————
原型模式(Prototype)
原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
解释:在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,然后如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适,然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使用new运算符去创建相同的类实例对象,此时我们一般思路就是想——只创建一个类实例对象,如果后面需要更多这样的实例,可以通过对原来对象拷贝一份来完成创建,这样在内存中不需要创建多个相同的类实例,从而减少内存的消耗和达到类实例的复用。
//客户端
class Client
{
static void Main(string[] args)
{
// 孙悟空 原型
MonkeyKingPrototype prototypeMonkeyKing = new ConcretePrototype("MonkeyKing");
// 变一个
MonkeyKingPrototype cloneMonkeyKing = prototypeMonkeyKing.Clone() as ConcretePrototype;
Console.WriteLine("Cloned1:\t"+cloneMonkeyKing.Id);
// 变两个
MonkeyKingPrototype cloneMonkeyKing2 = prototypeMonkeyKing.Clone() as ConcretePrototype;
Console.WriteLine("Cloned2:\t" + cloneMonkeyKing2.Id);
Console.ReadLine();
}
}
// 孙悟空原型
public abstract class MonkeyKingPrototype
{
public string Id { get; set; }
public MonkeyKingPrototype(string id)
{
this.Id = id;
}
// 克隆方法,即孙大圣说“变”
public abstract MonkeyKingPrototype Clone();
}
// 创建具体原型
public class ConcretePrototype : MonkeyKingPrototype
{
public ConcretePrototype(string id)
: base(id)
{ }
// 浅复制
public override MonkeyKingPrototype Clone()
{
// 调用MemberwiseClone方法实现的是浅拷贝,另外还有深拷贝
return (MonkeyKingPrototype)this.MemberwiseClone();
}
}