单例模式是一种创建型设计模式,可以保证一个类只有一个实例,并提供一个访问该实例的全局节点。
1.单例(Singleton)类声明了一个名为getInstance的静态方法来返回其所属类的一个相同实例。
2.单例的构造函数必须私有化,即对客户端(Client)隐藏。调用getInstance方法必须是获取单例对象的唯一方式。
方式1
public class Singleton
{
private Singleton() { }
private static Singleton instance;
public static Singleton GetInstance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
方式2:多线程单例
class SingletonThread
{
private SingletonThread() { } //私有化构造
private static volatile SingletonThread instance;
private static object lockHelper = new Object { };
public static SingletonThread GetInstance
{
get
{
// 双重校验,为避免额外的性能消耗。
if (instance == null)
{
// 当第一个线程运行到这里时,此时会对lock加锁。
// 当第二个线程运行该方法时,首先检测到lock加锁状态,该线程就会挂起等待第一个线程解锁。
lock (lockHelper)
{
if (instance == null)
{
instance = new SingletonThread();
}
}
}
return instance;
}
}
}
方式3
class SingletonRead
{
private SingletonRead() { }
//只要访问就会被执行静态构造器,不使用不会进行实例化
public static readonly SingletonRead Instance = new SingletonRead();
//等价于
//public static readonly SingletonRead Instance;
//static SingletonRead ()
//{
// Instance = new SingletonRead ();
//}
}
MVC设计模式一般指MVC框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。其设计目的是将M和V的实现代码分离,使同一个程序可以有不同的表现形式。
总之,我们通过MVC设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。
MVC并不适合小型甚至中型规模的项目,花费大量时间将MVC应用到规模并不是很大的应用程序,通常得不偿失,所以对于MVC设计模式的使用要根据具体的应用场景来决定。
新建StudentView.cs、StudentModel.cs和StudentController.cs,分别作为视图层、数据模型层和控制层。
StudentView.cs
using UnityEngine;
public class StudentView
{
public void PrintStudentDetails(string studentName, string studentRollNo)
{
Debug.Log("Student: ");
Debug.Log("Name: " + studentName);
Debug.Log("Roll No: " + studentRollNo);
}
}
StudentModel.cs
public class StudentModel
{
private string name;
private string rollNo;
public string Name { get => name; set => name = value; }
public string RollNo { get => rollNo; set => rollNo = value; }
}
StudentController.cs
public class StudentController
{
private StudentModel model;
private StudentView view;
public StudentController(StudentModel model, StudentView view)
{
this.model = model;
this.view = view;
}
public void SetStudentName(string name)
{
model.Name = name;
}
public string GetStudentName()
{
return model.Name;
}
public void SetStudentRollNo(string rollNo)
{
model.RollNo = rollNo;
}
public string GetStudentRollNo()
{
return model.RollNo;
}
public void UpdateView()
{
view.PrintStudentDetails(model.Name, model.RollNo);
}
}
新建MVCPatternDemo.cs,实现代码如下:
using UnityEngine;
public class MVCPatternDemo : MonoBehaviour
{
private void Awake()
{
StudentModel model = RetrieveStudentFromDatabase();
StudentView view = new StudentView();//创建一个视图:把学生详细信息输出到控制台
StudentController controller = new StudentController(model, view);
controller.UpdateView();
controller.SetStudentName("John");//更新模型数据
controller.UpdateView();
}
private static StudentModel RetrieveStudentFromDatabase()
{
StudentModel student = new StudentModel();
student.Name = "Robert";
student.RollNo = "10";
return student;
}
}
输出如下:
观察者模式(发布-订阅模式)属于行为型模式。在程序设计中,观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应。
解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变化都不会影响另一边的变化。
在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。
1.观察者(Observer):
观察者将自己注册到被观察者中,被观察者将观察者存放在一个容器里。
2.被观察(Subject):
被观察者发生变化时,从容器中得到所有注册过的观察者,将变化通知观察者。
3.撤销观察
观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。
观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现,这一点为程序提供了更大的灵活性。
新建ISubject.cs和IObserver.cs,分别作为抽象被观察者和抽象观察者。
新建ConcreteSubject.cs和ConcreteObserver.cs,分别作为具体被观察者和具体观察者。
脚本内容如下:
ISubject.cs
///
/// 抽象被观察者
///
public interface ISubject
{
///
/// 添加观察者
///
///
void AddObserver(IObserver observer);
///
/// 删除观察者
///
///
void RemoveObserver(IObserver observer);
///
/// 通知观察者
///
///
void NoticeObserver(string message);
}
IObserver.cs
///
/// 抽象观察者
///
public interface IObserver
{
///
/// 更新消息
///
///
void UpdateMessage(string message);
}
ConcreteSubject.cs
using System.Collections.Generic;
///
/// 具体被观察者
///
public class ConcreteSubject : ISubject
{
private List observers = new List();//存储观察者的容器
public void AddObserver(IObserver observer)
{
observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
observers.Remove(observer);
}
public void NoticeObserver(string message)
{
for (int i = 0; i < observers.Count; i++)
{
observers[i].UpdateMessage(message);
}
}
}
ConcreteObserver.cs
using UnityEngine;
///
/// 具体观察者
///
public class ConcreteObserver : IObserver
{
private string name;//观察者的名字
public ConcreteObserver(string name)
{
this.name = name;
}
public void UpdateMessage(string message)
{
Debug.Log(name + "---接到消息: " + message);
}
}
新建一个MyObserver.cs,内容如下:
using UnityEngine;
public class MyObserver : MonoBehaviour
{
private void Awake()
{
ConcreteSubject concreteSubject = new ConcreteSubject();//定义一个主题
ConcreteObserver concreteObserver01 = new ConcreteObserver("李先生");//实例化一个观察者
ConcreteObserver concreteObserver02 = new ConcreteObserver("王女士");//实例化一个观察者
//李先生和王女士订阅该主题
concreteSubject.AddObserver(concreteObserver01);
concreteSubject.AddObserver(concreteObserver02);
concreteSubject.NoticeObserver("俄罗斯和乌克兰打起来了");//通知所有观察者(订阅者)
//王女士取消订阅该主题
concreteSubject.RemoveObserver(concreteObserver02);
concreteSubject.NoticeObserver("国际形势逐步紧张起来");//通知所有观察者(订阅者)
}
}
最终输出如下: