设计模式(Design pattern):是帮助我们解决实际开发过程中的方法,该方法是为了降低对象之间的耦合度。
使用设计模式是为了可重用代码,让代码更容易被他人理解、保证代码可靠性。设计模式使代码编制真正工程化,设计模式就好比是软件工程的基石脉络。
单例模式,即所谓的一个类只能有一个实例,也就是类只能在内部实例化一次,然后提供这一实例,外部无法对此类实例化。
/**
* 单例:
* 1. 实例全局唯一
* 使用static(属于全局,并不属于类对象本身)实现
* 2. 实例化只能在类的内部发生
* 需要将构造函数私有化
* 3. 需要提供一个供外部访问的变量
*/
// 单例的实现
public class MySingleton
{
private static MySingleton _instance;
public static MySingleton Instance
{
get
{
if(_instance == null)
{
_instance = new MySingleton();
}
return _instance;
}
}
private MySingleton()
{
Debug.Log("单例模式");
}
public void Show()
{
Debug.Log("Show");
}
}
public class Simple
{
public Simple()
{
Debug.Log("构造函数");
}
}
public class Singleton : MonoBehaviour
{
void Start()
{
Simple single_1 = new Simple();
Simple single_2 = new Simple();
Simple single_3 = new Simple();
// 三个不同实例,哈希码不同
Debug.Log("single_1 = " + single_1.GetHashCode()
+ ", single_2 = " + single_2.GetHashCode()
+ ", single_3 = " + single_3.GetHashCode());
// 采用单例模式
MySingleton single1 = MySingleton.Instance;
single1.Show();
MySingleton single2 = MySingleton.Instance;
single2.Show();
MySingleton single3 = MySingleton.Instance;
single3.Show();
Debug.Log("single1 = " + single1.GetHashCode()
+ ", single2 = " + single2.GetHashCode()
+ ", single3 = " + single3.GetHashCode()); // 哈希码相同证明是同一对象,是单例模式
}
}
观察者模式:
又称 发布/订阅模式,观察者模式定义了一种 一对多 的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
(该模式常被用来实现事件处理系统。)
发布者 + 订阅者 = 观察者模式。
先设置一个主题(Subject)
让这个主题发布时可同时通知关心这个主题的观察者/订阅者
并且主题不必理会观察者/订阅者接下来会执行哪些操作
将“主题发生”与“功能执行”这两个操作解除绑定
C#中的事件系统(Event)便是使用的观察者模式
Unity中的所有事件(如UI点击事件)也是应用的观察者模式
/**
* 观察者模式
* 需求:猫来了,老鼠A, B, C惊吓逃走
*/
public class Animal
{
protected string Name;
public Animal(string name)
{
this.Name = name;
}
public virtual void Run(){ }
}
public class Cat : Animal
{
public Action actions; // 发布者
public Cat(string name) : base(name) { }
public void Coming()
{
Debug.Log( Name + "来了");
if(actions != null)
{
actions();
}
this.Run();
}
public override void Run()
{
Debug.Log(Name + "追老鼠");
}
}
public class Mouse : Animal
{
public Mouse(string name, Cat cat) : base(name)
{
cat.actions += this.Run; // 订阅者
}
public override void Run()
{
Debug.Log(Name + "逃跑");
}
}
public class Observer : MonoBehaviour
{
void Start()
{
Cat cat = new Cat("猫");
Animal mousea = new Mouse("老鼠A", cat);
Animal mouseb = new Mouse("老鼠B", cat);
Animal mousec = new Mouse("老鼠C", cat);
Animal moused = new Mouse("老鼠D", cat);
cat.Coming();
}
}
简单工厂模式:
特点:只生产一种品牌(类型)的产品,在工厂中动态创建。
一定程度上违背了开闭原则,在新增产品时需要修改简单工厂类
// 假设鼠标有两种:戴尔鼠标和惠普鼠标
//鼠标抽象类
public abstract class Mouse
{
public abstract void Print();
}
//戴尔鼠标
public class DellMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个Dell鼠标!");
}
}
//惠普鼠标
public class HpMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个惠普鼠标!");
}
}
///
/// 鼠标工厂类
///
public class MouseFactory
{
//从配置文件中读取品牌
private static readonly string brand = ConfigurationManager.AppSettings["brand"];
private Mouse mouse = null;
public Mouse CreateMouse()
{
switch (brand)
{
case "dell":
mouse = new DellMouse();
break;
case "hp":
mouse = new HpMouse();
break;
default:
break;
}
return mouse;
}
}
// 客户端
class Program
{
static void Main(string[] args)
{
//实例化一个工厂类
MouseFactory mouseFactory = new MouseFactory();
//通过工厂类创建鼠标
Mouse mouse1 = mouseFactory.CreateMouse();
Mouse mouse2 = mouseFactory.CreateMouse();
Mouse mouse3 = mouseFactory.CreateMouse();
Mouse mouse4 = mouseFactory.CreateMouse();
Mouse mouse5 = mouseFactory.CreateMouse();
mouse1.Print();
Console.ReadKey();
}
}
// 有效降低了客户端与DellMouse间的耦合
// 配置文件
<appSettings>
<add key="dbname" value="dell"/>
</appSettings>
工厂模式:
特点:只生产一种品牌(类型)的产品,在具体的子类工厂中创建。为了解决系列产品的问题,就有了抽象工厂模式。
工厂模式有效地解决了添加新产品必须要修改工厂类代码的问题,符合设计原则中的开闭原则。
工厂模式的本质是将具体实例的创建工作放在了具体子类工厂中进行,这造成一个新的问题:将选择实例类型的任务交给了客户端。
//鼠标抽象类
public abstract class Mouse
{
public abstract void Print();
}
//戴尔鼠标
public class DellMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个Dell鼠标!");
}
}
//惠普鼠标
public class HpMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个惠普鼠标!");
}
}
/*
工厂类只提供生产鼠标的抽象方法(或者接口),其子类生产具体的产品,如:
戴尔鼠标工厂继承于鼠标工厂,它只生产戴尔鼠标;
惠普鼠标工厂只生产惠普鼠标
*/
///
/// 鼠标工厂抽象类
///
public abstract class MouseFactory
{
public abstract Mouse CreateMouse();
}
//戴尔鼠标工厂
public class DellMouseFactroy : MouseFactory
{
public override Mouse CreateMouse()
{
return new DellMouse();//在具体的工厂中实例化产品
}
}
//惠普鼠标工厂
public class HpMouseFactory : MouseFactory
{
public override Mouse CreateMouse()
{
return new HpMouse();//在具体的工厂中实例化产品
}
}
// 客户端
static void Main(string[] args)
{
//生产一个戴尔鼠标
MouseFactory dellMouseFactory = new DellMouseFactroy();
Mouse dellMouse= dellMouseFactory.CreateMouse();
dellMouse.Print();
//生产一个惠普鼠标
MouseFactory hpMouseFactory = new HpMouseFactory();
Mouse hpMouse = hpMouseFactory.CreateMouse();
hpMouse.Print();
Console.ReadKey();
}
抽象工厂模式:
特点:抽象工厂可以生产多种产品。而简单工厂、工厂模式只能生产一种产品。即只有一种产品的抽象工厂就是工厂模式。
抽象工厂具有工厂模式的优点,对添加系列产品符合闭合原则(工厂模式的系列产品只有一种)。
抽象模式对添加新产品不符合开闭原则。
// 产品类
//鼠标抽象类
public abstract class Mouse
{
public abstract void Print();
}
//戴尔鼠标
public class DellMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个Dell鼠标!");
}
}
//惠普鼠标
public class HpMouse : Mouse
{
public override void Print()
{
Console.WriteLine("生产了一个惠普鼠标!");
}
}
//键盘抽象类
public abstract class Keybo
{
public abstract void Print();
}
//戴尔键盘类
public class DellKeybo : Keybo
{
public override void Print()
{
Console.WriteLine("生产了一个戴尔键盘!");
}
}
//惠普键盘
public class HpKeybo : Keybo
{
public override void Print()
{
Console.WriteLine("生产了一个惠普键盘!");
}
}
///
/// Pc产品工厂抽象类
///
public abstract class PcFactory
{
public abstract Mouse CreateMouse();
public abstract Keybo CreateKeybo();
}
//戴尔pc工厂
public class DellPcFactroy : PcFactory
{
public override Keybo CreateKeybo()
{
return new DellKeybo();
}
public override Mouse CreateMouse()
{
return new DellMouse();
}
}
//惠普pc工厂
public class HpPcFactory : PcFactory
{
public override Mouse CreateMouse()
{
return new HpMouse();
}
public override Keybo CreateKeybo()
{
return new HpKeybo();
}
}
// 客户端
class Program
{
static void Main(string[] args)
{
//生产一个戴尔鼠标/键盘
PcFactory dellFactory = new DellPcFactroy();
Mouse dellMouse= dellFactory.CreateMouse();
Keybo dellKeybo = dellFactory.CreateKeybo();
dellMouse.Print();
dellKeybo.Print();
//生产一个惠普鼠标/键盘
PcFactory hpFactory = new HpPcFactory();
Mouse hpMouse = hpFactory.CreateMouse();
Keybo hpKeybo = hpFactory.CreateKeybo();
hpMouse.Print();
hpKeybo.Print();
Console.ReadKey();
}
}
**将一个类的接口,转换成客户端希望的另一种接口。**适配器作为原始接口(类中本来具有的功能)和目标接口(客户端希望的功能)之间的桥梁。
类适配器,通过多重继承实现接口的匹配,C#不支持多重继承,故不考虑。
对象适配器,适配器模式的三个角色:
///
/// 安卓数据线,adaptee角色
///
public class AndroidLine
{
public void AndroidCharge()
{
Console.WriteLine("安卓数据线充电....");
}
}
///
/// 苹果手机充电接口,目标接口
///
public interface IApplecharge
{
void AppleCharge();
}
///
/// 苹果适配器 适配器角色
///
public class AppleAdapter : IAppleCharge
{
AndroidLine androidLine = new AndroidLine();//适配器内部包含一个Adaptee对象
public void AppleCharge()
{
androidLine.AndroidCharge(); //客户端调用时,表面上是用的是AppleCharge方法,本质还是用的AndroidCharge方法
}
}
// 客户端调用
class Program
{
static void Main(string[] args)
{
//获取一个target的实例
IApplyCharge applyAdapter = new ApplyAdapter();
applyAdapter.ApplyChange();//表面上用的苹果充电方法ApplyChange,本质上还是用的安卓充电方法AndriodChange。
Console.ReadKey();
}
}
系统想使用一个类,但是这个类的接口不符合系统的要求时使用适配器模式。
1. 提高代码复用,复用了Adaptee中的方法
2. 灵活性好,如没有关联的两个类A和类B,类A想借用类B的方法,可以在类A中添加一个类B的实例,然后调用类B实例的方法即可。