设计原则
使用设计模式的根本原因就是适应需求变化,提高代码的复用率,使程序更具有扩展性和可维护性。
SOLID原则和七大原则
想必S.O.L.I.D大家都知道,面向对象的五大设计原则。其中C#设计模式,又添加了依赖倒置、合成复用原则。总共是7大设计原则。
SRP(单一责任原则):只有一种原因会导致某个类的修改。让一个类只做一种类型责任,如需承担其他类型的责任时,应分解这个类。
OCP(开放封闭原则):软件实体(类,函数,模块等)应该对扩展开放,对修改关闭。每发生变化,需要通过添加新代码来增强类型的行为,而不是修改原有代码。
LSP(里氏替换原则):当子类替换掉他们的父类型,软件功能不受影响,父类才能真正使用,子类可以在父类的基础上添加新的行为。
ISP(接口隔离原则):使用专门的接口比使用单一的总接口要好很多。不要让单一接口承担过多的职责,针对职责进行接口分离。
DIP(依赖倒置原则):抽象不应该依赖于细节,细节应该依赖于抽象,面向接口编程。可以降低客户与具体实现的耦合。
CRP(合成复用原则):使用合成/聚合,尽量不要使用继承。在新的对象中,使用一些已有对象,让他成为新对象的一部分。
LOD(迪米特法则):一个模块或对象应尽量少与其他实体之间发生相互作用,使得系统相对独立,这样修改影响会减少,扩展会更容易。
创建型模式
用来创建对象的模式,抽象了实例化过程。有两个共同点。1.都将使用的具体类进行封装。2.隐藏类的实例是如何被组织创建的。
单例模式
确保一个类只有一个实例,并提供一个全局访问点。
常用场景:应用中有对象需要全局的且唯一
选择关键点:一个对象应用中出现多个实例是否会引起逻辑上或程序上的错误
劣势:以为是单例,却出现了多个实例
//使用单例模式创建类
public class Goddess
{
//封装具体类
private static Goddess _goddess; //使用lock锁,定义锁定的静态变量
private static object _obj = new object(); //创建全局访问点
public static Goddess CreateGoddess()
{
if (_goddess != null)
{
return _goddess;
}
//使用lock锁过滤
lock (_obj)
{
if (_goddess == null)
{
_goddess = new Goddess();
}
return _goddess;
}
}
}
单例模式
简单工厂
降低程序之间的耦合性,因为违反OCP原则,不推荐此种设计模式。可以使用多态来修改这种模式。
关于switch硬编码,当程序中出现一个switch,并且是最开始决定具体调用哪个类时,是可以接受的。
常用场景:需要在一堆产品中选择其中一个产品
选择关键点:一种产品是否可根据某个参数决定它的种类
劣势:工厂类不能正常工作
public static class Program
{
public static void Main(string[] args)
{
Cake cake = Bakery.Buy("AngleCake");
cake.Eat();
Console.ReadKey();
}
} //创建抽象产品类
public abstract class Cake
{
public abstract void Eat();
} //创建产品类
public class AngleCake : Cake
{
public override void Eat()
{
Console.WriteLine("产品执行方法");
}
}
//创建工厂类
public class Bakery
{
public static Cake Buy(string CakeType) {
switch (CakeType)
{
case "AngleCake":
return new AngleCake();
default:
throw new ArgumentException();
}
}
}
简单工厂
工厂模式
工厂模式把实例的推迟到子类,工厂类不进行创建产品,只提供必需实现的接口。
工厂模式,虽然把工厂方法进行抽象,但还是初始化时,还是需要指定。所以一个switch必不可少。
常用场景:希望工厂与产品的种类透明,不同的工厂可以提供客户不同的服务或功能
选择关键点:工厂类和产品类是否同生同灭的关系
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Bakery bak = new AngleBakery();
Cake cake = bak.Buy();
cake.Eat();
Console.ReadKey();
}
} //创建抽象产品类
public abstract class Cake
{
public abstract void Eat();
} //创建产品类
public class AngleCake : Cake
{
public override void Eat()
{
Console.WriteLine("产品执行方法");
}
}
//创建抽象工厂类
public abstract class Bakery
{
public abstract Cake Buy();
}
//创建工厂
public class AngleBakery : Bakery
{
public override Cake Buy()
{
return new AngleCake();
}
}
工厂模式
抽象工厂
抽象工厂可以创建一组产品,把具体产品实现推迟到子类。
跟工厂模式的区别就是,工厂模式只能创建一个产品,而抽象工厂可以创建一组产品。
常用场景:需要一个接口可以提供一堆产品,且不必知道产品的具体种类
选择关键点:这一堆产品是否需要一起提供,并且有一致的接口
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Bakery bak = new AngleBakery();
Cake cake = bak.ReadEat();
cake.Eat();
Beverage bever = bak.ReadDrink();
bever.Drink();
Console.ReadKey();
}
} //创建抽象产品类
public abstract class Cake
{
public abstract void Eat();
} //创建产品类
public class AngleCake : Cake
{
public override void Eat()
{
Console.WriteLine("产品执行方法");
}
}
public abstract class Beverage
{
public abstract void Drink();
}
public class Coke : Beverage
{
public override void Drink()
{
Console.WriteLine("产品执行方法");
}
}
//创建抽象工厂类
public abstract class Bakery
{
public abstract Cake ReadEat();
public abstract Beverage ReadDrink();
}
//创建工厂
public class AngleBakery : Bakery
{
public override Beverage ReadDrink()
{
return new Coke();
} public override Cake ReadEat()
{
return new AngleCake();
}
}
抽象工厂
原型工厂
只创建一个对象,如果需要另外创建对象,可以从将这个对象进行拷贝。避免创建对象的开销。
原型工厂进行拷贝是使用,浅拷贝MemberwiseClone。如果需要深拷贝,使用序列化。
常用场景:需要在运行时动态的创建指定实例种类的对象,或是需要复用其状态
选择关键点:创建出来的对象是否可以立即投入使用
劣势:应该用深度拷贝的时候,用浅拷贝
public static class Program
{
public static void Main(string[] args)
{
CostlyObject obj = new CostlyObject();
obj.Method();
CostlyObject obj1 = obj.Copy();
obj1.Method();
Console.ReadKey();
}
} //创建开销很大的对象
public class CostlyObject
{
//创建这个对象需要3秒,模拟开销很大
public CostlyObject() {
Thread.Sleep();
}
public void Method() {
Console.WriteLine("执行方法");
}
public CostlyObject Copy() {
return (CostlyObject)this.MemberwiseClone();
}
}
原型工厂
建造者模式
将一个产品的内部表示和产品的构造过程分解,从而可以使一个构造过程生成不同内部表示的产品对象。
使用各部分子对象通过一定步骤组合,变成一个复杂对象。
常用场景:需要构建一批过程相同但表示不同的产品,且构造过程非常复杂
选择关键点:各个产品的构造过程是否相同
劣势:指挥者不能正常工作
public static class Program
{
public static void Main(string[] args)
{
Command com = new Command();
Take take = new Take();
com.Read(take);
com.Go(take);
Console.ReadKey();
}
}
//创建复杂对象
public class ComplexObject
{
public List<string> list { get; set; } = new List<string>();
public void GetComplex()
{
foreach (var item in list)
{
Console.WriteLine(item);
}
}
}
//创建步骤任务
public class Take
{
ComplexObject _obj = new ComplexObject();
public void Eat()
{
_obj.list.Add("执行Eat方法");
}
public void Movie()
{
_obj.list.Add("执行Movie方法");
}
public ComplexObject GetComplex()
{
return _obj;
} }
//创建指挥者,组合步骤任务
public class Command
{
public void Read(Take take)
{
take.Movie(); take.Eat();
}
public void Go(Take take)
{
take.GetComplex().GetComplex();
}
}
建造者模式
结构性模式
讨论的是类和对象的结构,主要用来处理类或对象的组合。
包括两种类型:1.类结构型模式,指采用继承机制来组合接口或实现。2.对象结构型模式,通过组合对象的方式来实现新的功能。
适配器模式
适配器模式能够转换接口,使原本不能再一起工作的两个类在一起工作。经常用在类库复用,代码迁移等方面。
名字很高端,实际上最简单不过了。一个继承虚方法重写,就搞定了。不过适配器模式,会造成错误继承。
常用场景:需要使用一个类的功能,但类的接口不符合使用场景,需要定制适配器。或者一个接口方法过多,可以定义缺省适配器,让子类选择性覆盖适配器的方法。
选择关键点:定制适配器,是否有更加优良的替代方案。缺省适配器,是否可以不全部操作,且都有缺省方案。
劣势:无
public static class Program
{
public static void Main(string[] args)
{
BlackForesCake cake = new BlackForesCake();
cake.State();
cake = new AngleCake();
cake.State();
Console.ReadKey();
}
}
//创建待转换类
public class BlackForesCake
{
public virtual void State()
{
Console.WriteLine("执行BlackForesCake的State方法");
}
}
//创建转换类
public class AngleCake : BlackForesCake
{
public override void State()
{
Console.WriteLine("执行AngleCake的State方法");
}
}
适配器模式
桥接模式
桥接模式能够将抽象与实现解耦,使得两者可以独立的变化。可以把实现在进行抽象,构造到一个实例化结构中。
使用桥接模式,相当于多建立了一个中间人。但在重构中,不要进行Remove Middle Man操作。
常用场景:一个对象有多个维度的变化,需要将这些维度抽离出来,让其独立变化。
选择关键点:是否可以将对象拆分成多个不相关的维度
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Car car = new Auldey();
Remote mote = new Remote(car);
mote.Up();
Console.ReadKey();
}
}
//创建抽象化
public abstract class Car
{
public abstract void Up();
}
//创建实现
public class Auldey : Car
{
public override void Up()
{
Console.WriteLine("执行Up方法");
}
}
//创建桥接类,并重写方法
public class Remote
{
private Car _car;
public Remote(Car car)
{
_car = car;
}
public virtual void Up() {
Console.WriteLine("桥接模式方法重写");
_car.Up();
}
}
桥接模式
装饰器模式
可以动态的给一个对象添加一些额外功能,比继承更加灵活。使用this扩展方法会更加方便一点。
常用场景:一个类需要动态的添加功能,且这些功能可以相互叠加
选择关键点:添加的功能是否需要动态组装
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Goddess god = new Goddess();
Beautiful betGirl = new Beautiful(god);
betGirl.Speak();
Console.ReadKey();
}
}
//创建需要装饰的类
public class Goddess {
public void Speak() {
Console.WriteLine("执行Speak方法");
}
}
//创建装饰器类,对Goddess进行装饰
public class Beautiful {
private Goddess _goddess { get; set; }
public Beautiful(Goddess god) {
_goddess = god;
}
public void Speak() {
_goddess.Speak();
Console.WriteLine("执行装饰器方法");
}
}
装饰器模式
组合模式
组合模式将对象组合成树形结构,用来表示整体与部分的关系。
常用场景:有一个接口可以组成树形结构,并且需要向客户提供一致的接口,使客户端忽略简单元素与复杂元素
选择关键点:对外提供一致操作接口的结构是否可以转换成树形结构
劣势:结构不稳定或结构中的节点有递归关系
public static class Program
{
public static void Main(string[] args)
{
//组合实现类,变成需要的类
GoodCard card = new GoodCard();
card._cardList.Add(new A());
card._cardList.Add(new B());
card.PlayCard();
Console.ReadKey();
}
}
//创建抽象类
public abstract class Card
{
public abstract void PlayCard();
}
//创建实现类
public class A : Card
{
public override void PlayCard()
{
Console.WriteLine("A");
}
}
public class B : Card
{
public override void PlayCard()
{
Console.WriteLine("B");
}
}
//创建需要的类
public class GoodCard : Card
{
public List<Card> _cardList { get; set; } = new List<Card>();
public override void PlayCard()
{
foreach (var item in _cardList)
{
item.PlayCard();
}
}
}
组合模式
外观模式
外观模式可以将客户端与各个子系统接口。为子系统的一组接口提供一个统一的门面,使这个接口的子系统更加容易使用。
常用场景:一个子系统需要对外提供服务
选择关键点:子系统对外提供的服务是否需要依赖很多的类
劣势:子系统对外提供的服务的变化或子系统本身的不稳定
public static class Program
{
public static void Main(string[] args)
{
//调用统一的外观类方法
EatKFC KFC = new EatKFC();
KFC.Eat();
Console.ReadKey();
}
}
//定义子系统
public class LookKFC {
public bool Look() {
Console.WriteLine("执行Look");
return true;
}
}
public class BuyKFC {
public void Buy() {
Console.WriteLine("执行Buy");
}
}
//定义外观类,将子系统隐藏,公开统一接口
public class EatKFC {
LookKFC look { get; set; } = new LookKFC();
BuyKFC buy { get; set; } = new BuyKFC();
public void Eat() {
if (look.Look())
{
buy.Buy();
}
}
}
外观模式
享元模式
享元模式运用共享技术有效的支持细粒度对象,使其进行共享。节省实例化对象时的相同操作。
常用场景:一些状态相同的对象被大量的重复使用
选择关键点:被共享的对象是否可以将外部状态提取出来
劣势:没有将外部状态提取完全
public static class Program
{
public static void Main(string[] args)
{
TeamFactory fac = new TeamFactory();
Team A = fac.GetTeam("A");
A.GetTeam();
Team B = fac.GetTeam("A");
B.GetTeam();
Console.ReadKey();
}
}
//创建需要共享的对象
public class Team
{
private string _name { get; set; }
public Team(string name)
{
_name = name;
}
public void GetTeam()
{
Console.WriteLine(_name);
}
}
//创建共享工厂
public class TeamFactory
{
public Dictionary<string, Team> _teamList = new Dictionary<string, Team>();
public Team GetTeam(string name)
{
if (_teamList.ContainsKey(name))
{
return _teamList[name];
}
Console.WriteLine("新加入");
Team team = new Team(name);
_teamList.Add(name,team);
return team;
}
}
享元模式
代理模式
在系统开发中,有些对象不能直接访问,此时可通过一个代理对象来实现对目标对象的访问。
代理对象的用途很广,使用代理对象,可以解除客户端与目标对象的耦合关系。
常用场景:需要屏蔽一个或多个功能,复用另一个功能,可以使用静态代理。若是拦截一批类中的某些方法,在方法前后插入一些操作,可以使用动态代理
选择关键点:静态代理选择的关键点是否要复用被代理的部分功能。动态代理选择的关键点是能否将被代理的类当中,找到相同的切入点
劣势:切入点的不稳定
public static class Program
{
public static void Main(string[] args)
{
//调用
TaoBao taobao = new TaoBao();
taobao.Bread();
Console.ReadKey();
}
}
//创建目标类
public class Supermarket {
public void Bread() {
Console.WriteLine("执行Supermarket");
}
}
//创建代理类
public class TaoBao {
public Supermarket ket { get; set; } = new Supermarket();
public void Bread() {
Console.WriteLine("进行代理类额外处理");
ket.Bread();
}
}
代理模式
行为型模式
行为型模式对不同对象之间划分责任和算法抽象化。行为型模式不仅仅关于类和对象,还关于他们之间的相互作用。
行为性模式分为两种。
1.类的行为型模式:使用继承关系在几个类之间分配行为。
2.对象的行为型模式:使用对象聚合的方式来分配行为。
模板方法模式
模板方法模式是在一个抽象类中定义一个操作中的算法骨架,而将一些具体步骤延迟到子类中去实现。使得不改变算法结构的前提下,重新定义算法的特定步骤。
常用场景:一批子类的功能有可以提取的公共算法骨架
选择关键点:算法骨架是否牢固
劣势:无
public static class Program
{
public static void Main(string[] args)
{
FallInLove love = new Win();
love.Go();
Console.ReadKey();
}
}
//定义算法骨架
public abstract class FallInLove {
public abstract bool GoodWill();
public void Know() {
Console.WriteLine("Know");
}
public void Love() {
Console.WriteLine("Love");
}
public void Go() {
Know();
if (GoodWill())
{
Love();
}
}
}
//创建特定步骤
public class Win : FallInLove
{
public override bool GoodWill()
{
return true;
}
}
模板方法模式
命令模式
命令模式把一个请求或操作封装到一个对象中,通过对命令的抽象化来使得发出命令的责任和执行命令的责任分隔开。
常用场景:行为的请求者与行为的处理者耦合度过高
选择关键点:请求者是否不需要关心命令的执行只知道接受者
劣势:命令的种类无限制增长
public static class Program
{
public static void Main(string[] args)
{
G g = new G();
Command command = new Implementation(g);
M m = new M(command);
m.Go();
Console.ReadKey();
}
}
//将操作封装到对象中
public class G
{
public void OrderMeal()
{
Console.WriteLine("OrderMeal");
}
}
//搭建命令抽象类
public abstract class Command
{
protected G _g;
public Command(G g)
{
_g = g;
}
public abstract void Meal();
}
//创建命令实现类
public class Implementation : Command
{
public Implementation(G g) : base(g)
{ } public override void Meal()
{
base._g.OrderMeal();
}
}
//定义命令发出者
public class M
{
public Command _command { get; set; }
public M(Command command)
{
_command = command;
}
public void Go()
{
_command.Meal();
}
}
命令模式
迭代器模式
迭代器模式提供一种方法顺序访问一个集合对象中各个元素,而又无需暴露该对象的内部表示。
常用场景:需要迭代访问一个聚合对象中的各个元素,且不暴露聚合对象的内部表示
选择关键点:客户端是否关心遍历的次序
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Mahjong mah = new Mahjong();
foreach (var item in mah)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
} public class Mahjong : IEnumerator, IEnumerable
{
private int[] collection = new int[] { , , , , , , , , };
private int position = -; public object Current
{
get
{
return collection[position];
}
} public bool MoveNext()
{
position += ;
return position < collection.Length;
} public void Reset()
{
position = -;
} public IEnumerator GetEnumerator()
{
return new Mahjong();
}
}
迭代器模式
观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,对象在发生变化时,会通知所有观察者对象。
常用场景:需要将观察者与被观察者解耦或是观察者的种类不确定
选择关键点:观察者与被观察者是否是多对一的关系
劣势:观察者之间有过多的细节依赖
public static class Program
{
public static void Main(string[] args)
{
Fans M = new Fans("M");
GoddessWB wb = new GoddessWB("Info");
wb.AddFans(M.NewInformation);
wb.Update();
Console.ReadKey();
}
}
//定义通知数据
public class FansEventArgs : EventArgs
{
public FansEventArgs(string text)
{
Text = text;
}
public string Text { get; set; }
}
//定义通知集合
public delegate void FansHandler(object obj, FansEventArgs send);
//定义主题对象
public class GoddessWB
{
public FansHandler fansList;
public string _info { get; set; }
public GoddessWB(string Info)
{
_info = Info;
}
public void AddFans(FansHandler fans)
{
fansList += fans;
}
public void Update()
{
fansList?.Invoke(this, new FansEventArgs(_info));
}
}
//定义观察者
public class Fans
{
public string _name { get; set; }
public Fans(string Name)
{
_name = Name;
}
public void NewInformation(object obj, FansEventArgs send)
{
if (obj != null && obj is GoddessWB)
{
Console.WriteLine(_name + "-" + send.Text);
}
}
}
观察者模式
状态模式
允许一个对象再其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类。
常用场景:一个对象在多个状态下行为不同,且这些状态可互相转换
选择关键点:这些状态是否经常在运行时需要在不同的动态之间相互转换
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Account account = new Account();
account.love.Eat();
account.love.Eat();
Console.ReadKey();
}
}
//创建抽象类
public abstract class Love
{
public Account Account { get; set; }
public abstract void Eat();
}
//创建变化
public class Friend : Love
{
public Friend(Account acount)
{
Account = acount;
}
public override void Eat()
{
Console.WriteLine("Friend");
Account.love = new Lover();
}
}
public class Lover : Love
{
public override void Eat()
{
Console.WriteLine("Lover");
}
}
//创建状态类
public class Account
{
public Love love { get; set; }
public Account()
{
love = new Friend(this);
}
}
状态模式
中介者模式
定义了一个中介对象来封装一系列对象之间的交互关系。中介者使各个对象之间不需要显示地相互引用,从而降低耦合性。
常用场景:一个系列的对象交互关系十分复杂
选择关键点:复杂的交互关系是否有共性可被中介者承担
劣势:中介者无法工作
public static class Program
{
public static void Main(string[] args)
{
AbstractPlayer M = new M();
AbstractMediator mediator = new AbstractMediator(null);
mediator.list.Add(M);
mediator.State = new MWin(mediator);
mediator.Change();
Console.WriteLine(M.Money);
Console.ReadKey();
}
}
//创建抽象类
public abstract class AbstractPlayer
{
public int Money { get; set; }
//在修改方法中,接受中介者参数
public abstract void Change(int count, AbstractMediator mediator);
}
//创建实现
public class M : AbstractPlayer
{
public override void Change(int count, AbstractMediator mediator)
{
mediator.Change(count);
}
}
//创建中介者
public class AbstractMediator
{
public List<AbstractPlayer> list = new List<AbstractPlayer>();
public State State { get; set; }
public AbstractMediator(State state)
{
State = state;
}
public void Change(int Count)
{
State.Change(Count);
}
}
//定义状态
public abstract class State
{
protected AbstractMediator mediator;
public abstract void Change(int Count);
}
public class MWin : State
{
public MWin(AbstractMediator abMedia)
{
mediator = abMedia;
}
public override void Change(int Count)
{
foreach (AbstractPlayer item in mediator.list)
{
M m = item as M;
if (m != null)
{ m.Money += Count; }
else
{ item.Money -= Count; }
}
}
}
中介者模式
策略模式
策略模式是对算法的包装,把使用算法的责任和算法本身分割开,委派给不同的对象负责。将每个算法封装到具体公共接口中,从而使它们可以相互替代。
常用场景:算法或者策略需要经常替换
选择关键点:客户端是否依赖于某一个或若干个具体的策略
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Shop shop = new Shop(new WoMan());
double result = shop.BuyClothes();
Console.WriteLine(result);
Console.ReadKey();
}
} //定义可变的算法接口
interface IClothes {
double Buy(double money);
}
class WoMan : IClothes
{
public double Buy(double money)
{
return money * 0.87;
}
}
//定义算法主体
class Shop {
private IClothes clothes;
public Shop(IClothes clo) {
clothes = clo;
}
public double BuyClothes(double money) {
return clothes.Buy(money);
}
}
策略模式
责任链模式
某个请求需要多个对象进行处理,从而避免请求的发送者和接受之间的耦合。将这些对象形成一条链子,传递请求直到有对象处理它为止。
常用场景:一个请求的处理需要多个对象当中的一个或几个协作处理
选择关键点:对于每一个请求是否每个处理的对象都需要一次处理机会
劣势:无
public static class Program
{
public static void Main(string[] args)
{
Participate par = new A();
par.Next = new B();
par.Meet(new M());
par.Meet(new M());
Console.ReadKey();
}
}
public class M
{
public int _goodWill { get; set; }
public M(int GoodWill)
{
_goodWill = GoodWill;
}
}
//创建责任链条
public abstract class Participate
{
public Participate Next { get; set; }
public abstract void Meet(M m);
}
//设置责任链
public class A : Participate
{
public override void Meet(M m)
{
if (m._goodWill > )
{
Next.Meet(m);
}
else
{
Console.WriteLine("A");
}
}
}
public class B : Participate
{
public override void Meet(M m)
{
if (m._goodWill > )
{
Next.Meet(m);
}
else
{
Console.WriteLine("B");
}
}
}
责任链模式
访问者模式
访问者是封装一些施加于某种数据结构之上的操作。一旦这些操作需要修改,接受这个操作的数据结构则可以保持不变。
常用场景:作用于一个数据结构之上的操作经常变化
选择关键点:数据结构是否稳定以及操作是否经常变化
劣势:数据结构的不稳定
public static class Program
{
public static void Main(string[] args)
{
M m = new Beach();
m.Accept(new Goddess());
Console.ReadKey();
}
}
public interface IVisual
{
void Play(Beach b);
}
public class Goddess : IVisual
{
public void Play(Beach b)
{
Console.WriteLine("执行Play");
b.Go();
}
}
public abstract class M
{
public abstract void Accept(IVisual vistor);
public abstract void Go();
}
public class Beach : M
{
public override void Accept(IVisual vistor)
{
vistor.Play(this);
} public override void Go()
{
Console.WriteLine("Beach-GO");
}
}
访问者模式
备忘录模式
备忘录模式是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以恢复对象了。
常用场景:需要在对象的外部保存该对象的内部状态
选择关键点:是否可以在必要的时候,捕捉到对象内部状态
劣势:大对象的备份
//创建备忘录实体
public class ContantMemento {
public List<string> List { get; set; } = new List<string>();
public ContantMemento(List<string> list) {
List = list;
}
}
//操作备忘录
public class MobileOwner {
public List<string> List { get; set; } = new List<string>();
public MobileOwner(List<string> list) {
List = list;
}
//创建备忘录
public ContantMemento CreateMemento() {
return new ContantMemento(List);
}
//导入备忘录
public void RestoreMemento(ContantMemento memento) {
List = memento.List;
}
}
备忘录模式