23中设计模式
Posted xiaomao21
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23中设计模式相关的知识,希望对你有一定的参考价值。
1.简单工厂,拓展不方便
2.工厂方法好点,不过只能建造单种。
3.抽象工厂,也有缺点。
4.建造者模式,此时采购员只需要像电脑城的老板说自己要采购什么样的电脑就可以了,电脑城老板自然会把组装好的电脑送到公司。
5.原型模式 对象池?浅拷贝公用。
void Start() { // 孙悟空 原型 MonkeyKingPrototype prototypeMonkeyKing = new ConcretePrototype("223k"); // 变一个 MonkeyKingPrototype cloneMonkeyKing = prototypeMonkeyKing.Clone() as ConcretePrototype; print("Cloned1: " + cloneMonkeyKing.Id); // 变两个 MonkeyKingPrototype cloneMonkeyKing2 = prototypeMonkeyKing.Clone() as ConcretePrototype; print("Cloned2: " + cloneMonkeyKing2.Id); } public abstract class MonkeyKingPrototype { public string Id { get; set; } public MonkeyKingPrototype(string id) { this.Id = id; } // 克隆方法,即孙大圣说“变” public abstract MonkeyKingPrototype Clone(); } /// <summary> /// 创建具体原型 /// </summary> public class ConcretePrototype : MonkeyKingPrototype { public ConcretePrototype(string id) : base(id) { } /// <summary> /// 浅拷贝 /// </summary> /// <returns></returns> public override MonkeyKingPrototype Clone() { // 调用MemberwiseClone方法实现的是浅拷贝,另外还有深拷贝 return (MonkeyKingPrototype)this.MemberwiseClone(); } }
6.适配器模式,2种
7.桥接模式,桥接模式即将抽象部分与实现部分脱耦,使它们可以独立变化,用抽象类做属性
public class RemoteControl { private TV implementor; public TV Implementor { get { return implementor; } set { implementor = value; } } public virtual void On() { implementor.On(); } public virtual void Off() { implementor.Off(); } public virtual void SetChannel() { implementor.tuneChannel(); } } public abstract class TV { public abstract void On(); public abstract void Off(); public abstract void tuneChannel(); } public class ChangHong : TV { public override void On() { Debug.Log("长虹牌电视机已经打开了"); } public override void Off() { Debug.Log("长虹牌电视机已经关掉了"); } public override void tuneChannel() { Debug.Log("长虹牌电视机换频道"); } } public class ConcreteRemote : RemoteControl { public override void SetChannel() { base.SetChannel(); } } public class mytes : MonoBehaviour { void Start() { RemoteControl remoteControl = new ConcreteRemote(); remoteControl.Implementor = new ChangHong(); remoteControl.On(); remoteControl.SetChannel(); remoteControl.Off(); } }
8.装饰者模式 我们可以使用装饰者模式来动态地给一个对象添加额外的职责。
public abstract class Phone { public abstract void Print(); } /// <summary> /// 苹果手机,即装饰着模式中的具体组件类 /// </summary> public class ApplePhone : Phone { /// <summary> /// 重写基类方法 /// </summary> public override void Print() { Debug.Log("开始执行具体的对象——苹果手机"); } } /// <summary> /// 装饰抽象类,要让装饰完全取代抽象组件,所以必须继承自Photo /// </summary> public abstract class Decorator : Phone { private Phone phone; public Decorator(Phone p) { this.phone = p; } public override void Print() { if (phone != null) { phone.Print(); } } } /// <summary> /// 贴膜,即具体装饰者 /// </summary> public class Sticker : Decorator { public Sticker(Phone p) : base(p) { } public override void Print() { base.Print(); // 添加新的行为 AddSticker(); } /// <summary> /// 新的行为方法 /// </summary> public void AddSticker() { Debug.Log("现在苹果手机有贴膜了"); } } /// <summary> /// 手机挂件 /// </summary> public class Accessories : Decorator { public Accessories(Phone p) : base(p) { } public override void Print() { base.Print(); // 添加新的行为 AddAccessories(); } /// <summary> /// 新的行为方法 /// </summary> public void AddAccessories() { Debug.Log("现在苹果手机有漂亮的挂件了"); } }
9.组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以一致的方式处理单个对象以及对象的组合。
10.外观模式 然而外观模式与适配器模式不同的是:适配器模式是将一个对象包装起来以改变其接口,而外观是将一群对象 ”包装“起来以简化其接口。它们的意图是不一样的,适配器是将接口转换为不同接口,而外观模式是提供一个统一的接口来简化接口。
11.亨元模式
public abstract class Person { public abstract void BuyProduct(); } public class RealBuyPerson : Person { public override void BuyProduct() { Debug.Log("帮我买一个苹果3"); } } public class Friend : Person { RealBuyPerson realSubject; public override void BuyProduct() { if (realSubject == null) { realSubject = new RealBuyPerson(); } this.PreBuyProduct(); realSubject.BuyProduct(); this.PostBuyProduct(); } public void PreBuyProduct() { Debug.Log("我怕弄糊涂,需要一张清单。"); } public void PostBuyProduct() { Debug.Log("买完了,要分类给别人"); } } public class mytes : MonoBehaviour { void Start() { Person proxy = new Friend(); proxy.BuyProduct(); } }
12. 模板方法模式
public abstract class Vegetabel { public void CookVegetabel() { this.pourOil(); this.HeatOil(); this.pourVegetable(); this.stir_fry(); } // 第一步倒油 public void pourOil() { Console.WriteLine("倒油"); } // 把油烧热 public void HeatOil() { Console.WriteLine("把油烧热"); } // 油热了之后倒蔬菜下去,具体哪种蔬菜由子类决定 public abstract void pourVegetable(); // 开发翻炒蔬菜 public void stir_fry() { Console.WriteLine("翻炒"); } } public class Spinach : Vegetabel { public override void pourVegetable() { Debug.Log("倒进锅中"); } } public class mytes : MonoBehaviour { void Start() { } }
13.命令模式
// 教官,负责调用命令对象执行请求 public class Invoke { public Command _command; public Invoke(Command command) { this._command = command; } public void ExecuteCommand() { _command.Action(); } } // 命令抽象类 public abstract class Command { // 命令应该知道接收者是谁,所以有Receiver这个成员变量 protected Receiver _receiver; public Command(Receiver receiver) { this._receiver = receiver; } // 命令执行方法 public abstract void Action(); } // public class ConcreteCommand :Command { public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Action() { // 调用接收的方法,因为执行命令的是学生 _receiver.Run1000Meters(); } } // 命令接收者——学生 public class Receiver { public void Run1000Meters() { Console.WriteLine("跑1000米"); } } // 院领导 class Program { static void Main(string[] args) { // 初始化Receiver、Invoke和Command Receiver r = new Receiver(); Command c = new ConcreteCommand(r); Invoke i = new Invoke(c); // 院领导发出命令 i.ExecuteCommand(); } }
14.迭代器模式就是用迭代器类来承担遍历集合元素的职责。
在下面的情况下可以考虑使用迭代器模式:
系统需要访问一个聚合对象的内容而无需暴露它的内部表示。
系统需要支持对聚合对象的多种遍历。
系统需要为不同的聚合结构提供一个统一的接口。
15.
// 抽象聚合类 public interface IListCollection { Iterator GetIterator(); } // 迭代器抽象类 public interface Iterator { bool MoveNext(); object GetCurrent(); void Next(); void Reset(); } // 具体聚合类 public class ConcreteList : IListCollection { int[] collection; public ConcreteList() { collection = new int[] { 2, 4, 6, 8 }; } public Iterator GetIterator() { return new ConcreteIterator(this); } public int Length { get { return collection.Length; } } public int GetElement(int index) { return collection[index]; } } // 具体迭代器类 public class ConcreteIterator : Iterator { // 迭代器要集合对象进行遍历操作,自然就需要引用集合对象 private ConcreteList _list; private int _index; public ConcreteIterator(ConcreteList list) { _list = list; _index = 0; } public bool MoveNext() { if (_index < _list.Length) { return true; } return false; } public object GetCurrent() { return _list.GetElement(_index); } public void Reset() { _index = 0; } public void Next() { if (_index < _list.Length) { _index++; } } } public class mytes : MonoBehaviour { void Start() { Iterator iterator; IListCollection list = new ConcreteList(); iterator = list.GetIterator(); while (iterator.MoveNext()) { int i = (int)iterator.GetCurrent(); Debug.Log(i.ToString()); iterator.Next(); } } }
16.观察者模式
17.中介模式 现实生活中,中介者的存在是不可缺少的,如果没有了中介者,我们就不能与远方的朋友进行交流了。而在软件设计领域,为什么要使用中介者模式呢?如果不使用中介者模式的话,各个同事对象将会相互进行引用,如果每个对象都与多个对象进行交互时,将会形成如下图所示的网状结构。
// 抽象牌友类 public abstract class AbstractCardPartner { public int MoneyCount { get; set; } public AbstractCardPartner() { MoneyCount = 0; } public abstract void ChangeCount(int Count, AbstractMediator mediator); } // 牌友A类 public class ParterA : AbstractCardPartner { // 依赖与抽象中介者对象 public override void ChangeCount(int Count, AbstractMediator mediator) { mediator.AWin(Count); } } // 牌友B类 public class ParterB : AbstractCardPartner { // 依赖与抽象中介者对象 public override void ChangeCount(int Count, AbstractMediator mediator) { mediator.BWin(Count); } } // 抽象中介者类 public abstract class AbstractMediator { protected AbstractCardPartner A; protected AbstractCardPartner B; public AbstractMediator(AbstractCardPartner a, AbstractCardPartner b) { A = a; B = b; } public abstract void AWin(int count); public abstract void BWin(int count); } // 具体中介者类 public class MediatorPater : AbstractMediator { public MediatorPater(AbstractCardPartner a, AbstractCardPartner b) : base(a, b) { } public override void AWin(int count) { A.MoneyCount += count; B.MoneyCount -= count; } public override void BWin(int count) { B.MoneyCount += count; A.MoneyCount -= count; } } public class mytes : MonoBehaviour { void Start() { AbstractCardPartner A = new ParterA(); AbstractCardPartner B = new ParterB(); // 初始钱 A.MoneyCount = 20; B.MoneyCount = 20; AbstractMediator mediator = new MediatorPater(A, B); // A赢了 A.ChangeCount(5, mediator); Debug.Log("A 现在的钱是:{0}" + A.MoneyCount);// 应该是25 Debug.Log("B 现在的钱是:{0}" + B.MoneyCount); // 应该是15 } }
18.状态模式 状态和行为,状态的改变引起行为的改变。下面利用观察者模式和状态者模式来完善中介者模式?(高深啊)
19.策略者模式 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开,委派给不同的对象负责。策略模式通常把一系列的算法包装到一系列的策略类里面。用一句话慨括策略模式就是——“将每个算法封装到不同的策略类中,使得它们可以互换”
// 所得税计算策略 public interface ITaxStragety { double CalculateTax(double income); } // 个人所得税 public class PersonalTaxStrategy : ITaxStragety { public double CalculateTax(double income) { return income * 0.12; } } // 企业所得税 public class EnterpriseTaxStrategy : ITaxStragety { public double CalculateTax(double income) { return (income - 3500) > 0 ? (income - 3500) * 0.045 : 0.0; } } public class InterestOperation { private ITaxStragety m_strategy; public InterestOperation(ITaxStragety strategy) { this.m_strategy = strategy; } public double GetTax(double income) { return m_strategy.CalculateTax(income); } } public class mytes : MonoBehaviour { void Start() { // 个人所得税方式 InterestOperation operation = new InterestOperation(new PersonalTaxStrategy()); Console.WriteLine("个人支付的税为:{0}", operation.GetTax(5000.00)); // 企业所得税 operation = new InterestOperation(new EnterpriseTaxStrategy()); Console.WriteLine("企业支付的税为:{0}", operation.GetTax(50000.00)); } }
20.责任链模式
我们就需要多重if-else语句来进行判断,但当加入一个新的条件范围时,我们又不得不去修改原来设计的方法来再添加一个条件判断,这样的设计显然违背了“开-闭”原则。这时候,可以采用责任链模式来解决这样的问题 开闭原装有很多啊?
namespace ChainofResponsibility { // 采购请求 public class PurchaseRequest { // 金额 public double Amount { get; set; } // 产品名字 public string ProductName { get; set; } public PurchaseRequest(double amount, string productName) { Amount = amount; ProductName = productName; } } // 审批人,Handler public abstract class Approver { public Approver NextApprover { get; set; } public string Name { get; set; } public Approver(string name) { this.Name = name; } public abstract void ProcessRequest(PurchaseRequest request); } // ConcreteHandler public class Manager : Approver { public Manager(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 10000.0) { Console.WriteLine("{0}-{1} approved the request of purshing {2}", this, Name, request.ProductName); } else if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,副总 public class VicePresident : Approver { public VicePresident(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 25000.0) { Console.WriteLine("{0}-{1} approved the request of purshing {2}", this, Name, request.ProductName); } else if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,总经理 public class President :Approver { public President(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 100000.0) { Console.WriteLine("{0}-{1} approved the request of purshing {2}", this, Name, request.ProductName); } else { Console.WriteLine("Request需要组织一个会议讨论"); } } } class Program { static void Main(string[] args) { PurchaseRequest requestTelphone = new PurchaseRequest(4000.0, "Telphone"); PurchaseRequest requestSoftware = new PurchaseRequest(10000.0, "Visual Studio"); PurchaseRequest requestComputers = new PurchaseRequest(40000.0, "Computers"); Approver manager = new Manager("LearningHard"); Approver Vp = new VicePresident("Tony"); Approver Pre = new President("BossTom"); // 设置责任链 manager.NextApprover = Vp; Vp.NextApprover = Pre; // 处理请求 manager.ProcessRequest(requestTelphone); manager.ProcessRequest(requestSoftware); manager.ProcessRequest(requestComputers); Console.ReadLine(); } } }
21.访问者模式
访问者模式是封装一些施加于某种数据结构之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保存不变。访问者模式适用于数据结构相对稳定的系统, 它把数据结构和作用于数据结构之上的操作之间的耦合度降低,使得操作集合可以相对自由地改变。
数据结构的每一个节点都可以接受一个访问者的调用,此节点向访问者对象传入节点对象,而访问者对象则反过来执行节点对象的操作。这样的过程叫做“双重分派”。节点调用访问者,将它自己传入,访问者则将某算法针对此节点执行。
此时,我们可以使用访问者模式来解决这个问题,即把作用于具体元素的操作由访问者对象来调用。此时客户端与元素的Print方法就隔离开了。此时,如果需要添加打印访问时间的需求时,此时只需要再添加一个具体的访问者类即可。此时就不需要去修改元素中的Print()方法了。访问者模式的目的是把操作从数据结构中分离出来。
namespace VistorPattern { // 抽象元素角色 public abstract class Element { public abstract void Accept(IVistor vistor); public abstract void Print(); } // 具体元素A public class ElementA :Element { public override void Accept(IVistor vistor) { // 调用访问者visit方法 vistor.Visit(this); } public override void Print() { Console.WriteLine("我是元素A"); } } // 具体元素B public class ElementB :Element { public override void Accept(IVistor vistor) { vistor.Visit(this); } public override void Print() { Console.WriteLine("我是元素B"); } } // 抽象访问者 public interface IVistor { void Visit(ElementA a); void Visit(ElementB b); } // 具体访问者 public class ConcreteVistor :IVistor { // visit方法而是再去调用元素的Accept方法 public void Visit(ElementA a) { a.Print(); } public void Visit(ElementB b) { b.Print(); } } // 对象结构 public class ObjectStructure { private ArrayList elements = new ArrayList(); public ArrayList Elements { get { return elements; } } public ObjectStructure() { Random ran = new Random(); for (int i = 0; i < 6; i++) { int ranNum = ran.Next(10); if (ranNum > 5) { elements.Add(new ElementA()); } else { elements.Add(new ElementB()); } } } } class Program { static void Main(string[] args) { ObjectStructure objectStructure = new ObjectStructure(); foreach (Element e in objectStructure.Elements) { // 每个元素接受访问者访问 e.Accept(new ConcreteVistor()); } Console.Read(); } } }
22.备忘录模式
从字面意思就可以明白,备忘录模式就是对某个类的状态进行保存下来,等到需要恢复的时候,可以从备忘录中进行恢复。生活中这样的例子经常看到,如备忘电话通讯录,备份操作操作系统,备份数据库等。
备忘录模式的具体定义是:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以把该对象恢复到原先的状态。
还能保存多个对象点先不看了。
// 联系人 public class ContactPerson { public string Name { get; set; } public string MobileNum { get; set; } } // 发起人 public class MobileOwner { // 发起人需要保存的内部状态 public List<ContactPerson> ContactPersons { get; set; } public MobileOwner(List<ContactPerson> persons) { ContactPersons = persons; } // 创建备忘录,将当期要保存的联系人列表导入到备忘录中 public ContactMemento CreateMemento() { // 这里也应该传递深拷贝,new List方式传递的是浅拷贝, // 因为ContactPerson类中都是string类型,所以这里new list方式对ContactPerson对象执行了深拷贝 // 如果ContactPerson包括非string的引用类型就会有问题,所以这里也应该用序列化传递深拷贝 return new ContactMemento(new List<ContactPerson>(this.ContactPersons)); } // 将备忘录中的数据备份导入到联系人列表中 public void RestoreMemento(ContactMemento memento) { // 下面这种方式是错误的,因为这样传递的是引用, // 则删除一次可以恢复,但恢复之后再删除的话就恢复不了. // 所以应该传递contactPersonBack的深拷贝,深拷贝可以使用序列化来完成 this.ContactPersons = memento.contactPersonBack; } public void Show() { Console.WriteLine("联系人列表中有{0}个人,他们是:", ContactPersons.Count); foreach (ContactPerson p in ContactPersons) { Console.WriteLine("姓名: {0} 号码为: {1}", p.Name, p.MobileNum); } } } // 备忘录 public class ContactMemento { // 保存发起人的内部状态 public List<ContactPerson> contactPersonBack; public ContactMemento(List<ContactPerson> persons) { contactPersonBack = persons; } } // 管理角色 public class Caretaker { public ContactMemento ContactM { get; set; } } class Program { static void Main(string[] args) { List<ContactPerson> persons = new List<ContactPerson>() { new ContactPerson() { Name= "Learning Hard", MobileNum = "123445"}, new ContactPerson() { Name = "Tony", MobileNum = "234565"}, new ContactPerson() { Name = "Jock", MobileNum = "231455"} }; MobileOwner mobileOwner = new MobileOwner(persons); mobileOwner.Show(); // 创建备忘录并保存备忘录对象 Caretaker caretaker = new Caretaker(); caretaker.ContactM = mobileOwner.CreateMemento(); // 更改发起人联系人列表 Console.WriteLine("----移除最后一个联系人--------"); mobileOwner.ContactPersons.RemoveAt(2); mobileOwner.Show(); // 恢复到原始状态 Console.WriteLine("-------恢复联系人列表------"); mobileOwner.RestoreMemento(caretaker.ContactM); mobileOwner.Show(); Console.Read(); } }
23.浅拷贝深拷贝
以上是关于23中设计模式的主要内容,如果未能解决你的问题,请参考以下文章