1024 观后感
读完设计模式之后发现之前的许多项目代码可以进行优化,精简。在其他项目中也可以对我这种外行菜鸟有更多的启发。但是后面21~28设计模式只是粗略读了一下,以后应用到的时候在进行专项补充吧。
前面的几个设计模式准备在以后几个项目中进行尝试或者年底将之前的项目使用设计模式进行优化,练习一下加深印象。
面向对象设计
三个基本特征
- 封装
- 继承
- 多态
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
第一章简单工厂模式
实现
题目:通过控制台程序让用户输入指定值和计算方法进行求值
我的第一想法会是建四个类分别代表‘+’,‘-’,‘*’,‘/’通过调用四个方法进行分别的计算,不够这种方式在main
里面会显得特别臃肿,通过继承类,重写方法,并将方法放在单独的计算类中会让整个代码看上去更有条理性。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please enter two number: ");
Console.WriteLine("The first Number: ");
string numberA = Console.ReadLine();
Console.WriteLine("The Second Number: ");
string numberB = Console.ReadLine();
double doubleA, doubleB;
if(double.TryParse(numberA,out doubleA)&&double.TryParse(numberB,out doubleB))
{
Console.WriteLine("Please enter your operation : '+' '-'");
string o = Console.ReadLine();
var operation = GetOperation(o);
operation.NumberA = doubleA;
operation.NumberB = doubleB;
Console.WriteLine($"{operation.GetResult()}");
}
else
{
throw new InvalidOperationException();
}
}
public static Operation GetOperation(string operation)
{
Operation oper = null;
switch (operation)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
}
return oper;
}
}
public class Operation
{
private double _numberA = 0;
private double _numberB = 0;
public double NumberA
{
get => _numberA;
set { _numberA = value; }
}
public double NumberB
{
get => _numberB;
set { _numberB = value; }
}
public virtual double GetResult()
{
double result = 0;
return result;
}
}
class OperationAdd : Operation
{
public override double GetResult()
{
return NumberA + NumberB;
}
}
class OperationSub : Operation
{
public override double GetResult()
{
return NumberA - NumberB;
}
}
第二章 策略模式
理解
策略模式与工厂模式的模式都是通过一个中间类将算法进行分隔,降低各个功能之间的耦合度,在后期增加或修改相应功能时,尽可能小的减少对其他算法的影响。策略模式更加着重于将算法策略与结果进行分隔,由于是刚接触设计模式,目前在我看来两者的底层逻辑是一样的思路,只不过实现的方式出现一定的差别。
策略模式(Strategy):他定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的用户
#region 策略模式 Strategy
abstract class Strategy
{
public abstract void AlgorithmInterface();
}
class ConcreteStrategyA:Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法A实现!");
}
}
class ConcreteStrategyB:Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法B实现!");
}
}
class ConcreteStrategyC:Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法C实现!");
}
}
class Context
{
private Strategy _strategy;
public Context(Strategy strategy)
{
this._strategy = strategy;
}
public void ContextInterface()
{
_strategy.AlgorithmInterface();
}
}
#endregion
将工厂模式与策略模式结合
按照书中的案例,将会使主窗口的判断减少许多,逻辑性可以在Context
类中展示出来
#region 工厂模式
class CashFactory
{
private static CashSuper ce;
public CashFactory(string type)
{
ce = null;
switch (type)
{
case "正常收费":
ce = new CashNormal();
break;
case "满300-30":
ce = new CashReturn("300","30");
break;
case "打八折":
ce = new CashRebate("0.8");
break;
}
}
public double ConTextInterface(double money)
{
return ce.AcceptCash(money);
}
}
class CashContext
{
private CashSuper _cashSuper;
public CashContext(CashSuper cashSuper)
{
_cashSuper = cashSuper;
}
public double ContextInterface(double money)
{
return _cashSuper.AcceptCash(money);
}
}
//抽象类
abstract class CashSuper
{
public abstract double AcceptCash(double money);
}
/// <summary>
/// 正常收费
/// </summary>
class CashNormal:CashSuper
{
public override double AcceptCash(double money)
{
Console.WriteLine("收费: {0}",money);
return money;
}
}
/// <summary>
/// 折扣时的费用
/// </summary>
class CashRebate:CashSuper
{
private double moneyRebate = 1d;
/// <summary>
/// 输入折扣额度
/// </summary>
/// <param name="moneyRebate"></param>
public CashRebate(String moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
}
public override double AcceptCash(double money)
{
Console.WriteLine("收费:{0} 利率:{1}",money * moneyRebate,moneyRebate);
return money * moneyRebate;
}
}
/// <summary>
/// 返利(300-30)
/// </summary>
class CashReturn:CashSuper
{
private double returnMoney = 0.0d;//返利金额
private double targetMoney = 0.0d;//满减金额
public CashReturn(string target,string re)
{
this.returnMoney = double.Parse(re);
this.targetMoney = double.Parse(target);
}
public override double AcceptCash(double money)
{
if (money>=targetMoney)//用户获得返利条件
{
double count = money / targetMoney;
double m = money - Math.Floor(count) * returnMoney;
Console.WriteLine("收费:{0} ,活动为满{1}减{2}",m,targetMoney,returnMoney);
return m;
}
else//没有达到返利条件
{
return money;
}
}
}
#endregion
单一职责原则
单一职责原则(SRP):就一个类而言,应该仅有一个引起它变化的原因
开放-封闭原则
开放-封闭原则:是说软件实体(类、模块、函数等等)应该可以拓展,但是不可修改
- 对于拓展是开放的(Open for extension)
- 对于更改是封闭的(Closed for modification)
不恰当的例子:例题中抽象类开放的,实现的类为封闭的并且只有一个职责
依赖倒转原则
依赖倒转原则:
- 高层模块不应该依赖底层模块,两个都应该依赖抽象
- 抽象不应该依赖细节,细节应该依赖抽象
里氏代换原则[LSP]:子类型必须能够替换掉他们的父类型
一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而察觉不出父类与子类的区别。换而言之,如果在软件实体中将所有父类用子类替代,程序的行为没有变化。
第六章 装饰模式
装饰模式是利用SerComponent对对象进行包装,这样每个装饰对象的实现和如何使用这个这个对象分离开了,每个装饰对象只关注自己的功能,不需要关心如何被添加到对象链当中
在我看来这个和之前的工厂模式和策略模式相比下,降低了耦合度,不仅使每个大模块不相互打扰,小方法之间也建立了隔离。
abstract class Component
{
public abstract void Operation();
}
class ConcreteComponent : Component
{
public override void Operation()
{
Console.WriteLine("具体对象的操作!");
}
}
abstract class Decorator : Component
{
protected Component _component;
public void SetCompont(Component component)
{
_component = component;
}
public override void Operation()
{
if (_component != null)
{
_component.Operation();
}
}
}
class ConcreteDecoratorA : Decorator
{
public string AddStates;
public override void Operation()
{
base.Operation();
AddStates = "New States";
Console.WriteLine("具体对象A的操作方式");
}
}
class ConcreteDeciratorB : Decorator
{
public void AddBehavior()
{
Console.WriteLine("behavor!!!");
}
public override void Operation()
{
base.Operation();
AddBehavior();
Console.WriteLine("具体对象B的实现方法!");
}
}
书中的衣服装饰
static void Main(string[] args)
{
//ConcreteComponent concrete = new ConcreteComponent();
//ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
//ConcreteDeciratorB deciratorB = new ConcreteDeciratorB();
//decoratorA.SetCompont(concrete);
//deciratorB.SetCompont(decoratorA);
//deciratorB.Operation();
//Console.Read();
Person person = new Person("小菜");
TShirts shirts = new TShirts();
BigTrousers bigTrousers = new BigTrousers();
shirts.Decorate(person);
bigTrousers.Decorate(shirts);
bigTrousers.Show();
Console.Read();
}
/// <summary>
/// 人物
/// </summary>
class Person
{
public Person() { }
private string name;
public Person(string name)
{
this.name = name;
}
public virtual void Show()//虚拟类,可以不被实现,但是类中必须有括号{}
{
Console.WriteLine("{0}的装扮为:", this.name);
}
}
class Finery : Person
{
protected Person person;
public void Decorate(Person component)
{
person = component;
}
public override void Show()
{
if (person != null)
{
person.Show();
}
}
}
class TShirts : Finery
{
public override void Show()
{
base.Show();
Console.WriteLine("T恤");
}
}
class BigTrousers : Finery
{
public override void Show()
{
base.Show();
Console.WriteLine("马裤");
}
}
代理模式
代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。
应用:
- 远程代理,也就是为一个对象在不同地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
- 虚拟代理,根据需要创建开销很大的对象。通过它存放实例化需要很长时间的真实对象。
- 安全代理,用来控制真实对象访问时的权限。
- 只能指引,是指当前调用事实对象时,代理处理另外一些事。
前面的简单工厂模式、策略模式与装饰模式,都是在实现多个功能的组合匹配下的实现模式,通过降低耦合性,实现可拓展,保护原有类。
代码
static void Main(string[] args)
{
RealSubject realSubject = new RealSubject();
Proxy proxy = new Proxy(realSubject);
proxy.Request();
}
abstract class Subject
{
public abstract void Request();//抽象类,类中不需要有内容,必须被强制重写
}
class RealSubject : Subject
{
public override void Request()
{
Console.WriteLine("真实的请求!!!");
}
}
class Proxy : Subject
{
RealSubject realSubject;
public Proxy(RealSubject realSubject) => this.realSubject = realSubject;
public override void Request()
{
if (realSubject != null)
{
realSubject.Request();
}
}
}
##工厂模式
工厂方法模式(Factory Method):定义一个用于创建对象的借口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
code示例,修改了简单工厂方法,创建一个接口,通过继承接口分别创建方法类
static void Main(string[] args)
{
/*
* 使用工厂方法,后期增加新的功能,在使用时只需要修改一步便可
* 这个区别于简单工厂方法,需要新增计算类并在工厂方法中新增选项
*/
IOperation iOper = new Factory.SubOperationFactory();
Operation operation = iOper.CreatOperation();
operation.Num1 = 1;
operation.Num2 = 2;
var result = operation.GetResult();
Console.WriteLine(result);
Console.Read();
}
/*
* 工厂模式,为每个类建立一个工厂方法
* 开放-封闭原则:对于拓展是开放的,对于修改是封闭的
* 相较于简单工厂模式,如果新增解决办法需要修改工厂类
* 违背了开放封闭原则,在后期改动较大的情况下使用工厂
* 办法要由于简单工厂办法
*/
abstract class Operation
{
private double _num1;
private double _num2;
public double Num1
{
get => _num1;
set => _num1 = value;
}
public double Num2
{
get => _num2;
set => _num2 = value;
}
public abstract double GetResult();
}
class AddOperation:Operation
{
public override double GetResult()
{
return Num1 + Num2;
}
}
class SubOperation:Operation
{
public override double GetResult()
{
return Num1 - Num2;
}
}
interface IOperation
{
Operation CreatOperation();
}
class Factory
{
public class AddOperationFactory:IOperation
{
public Operation CreatOperation()
{
Operation operation = new AddOperation();
return operation;
}
}
public class SubOperationFactory:IOperation
{
public Operation CreatOperation()
{
Operation operation = new SubOperation();
return operation;
}
}
}
原型模式
原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
原型模式其实就是从一个对象再创建另外一个可创建对象,而且不许知道任何创建的细节
static void Main(string[] args)
{
Resume resume1 = new Resume("小明");
resume1.SetAgeAndSex("男","23");
resume1.SetWorkInformation("2020-10-08","甲");
Resume resume2 = (Resume) resume1.Clone();
resume2.SetWorkInformation("2020-10-08","乙");
Console.WriteLine("resume1's workInformation:workDate={0},company={1}",resume1.WorkInformation.WorkDate,resume1.WorkInformation.Company);
Console.WriteLine("resume2's workInformation:workDate={0},company={1}",resume2.WorkInformation.WorkDate,resume2.WorkInformation.Company);
Console.ReadLine();
}
/*
* 需要了解浅层复制,值复制与引用复制
* .NET通过引用ICloneable实现克隆
*/
abstract class Prototype
{
private string id;
public string Id
{
get => id;
set => id = value;
}
public Prototype(string id)
{
this.id = id;
}
public abstract Prototype Clone();
}
class ConcretePrototype:Prototype
{
public ConcretePrototype(string id) : base(id)
{
}
public override Prototype Clone()
{
return (Prototype) this.MemberwiseClone();//如果是值类型,则逐位复制,如果是引用类型将会复制引用将不会复制对象
}
}
class WorkInformation:ICloneable
{
private string workDate;
private string company;
public string WorkDate
{
get => workDate;
set => workDate = value;
}
public string Company
{
get => company;
set => company = value;
}
public object Clone()
{
return (object)this.MemberwiseClone();
}
}
class Resume:ICloneable
{
private string name;
private string sex;
private string age;
private WorkInformation _workInformation;
public Resume(string name)
{
this.name = name;
_workInformation = new WorkInformation();
}
private Resume(WorkInformation workInformation)
{
_workInformation = (ConsoleApp.WorkInformation) workInformation.Clone();
}
public void SetAgeAndSex(string sex, string age)
{
this.age = age;
this.sex = sex;
}
public void SetWorkInformation(string workDate, string company)
{
_workInformation.Company = company;
_workInformation.WorkDate = workDate;
}
public WorkInformation WorkInformation => _workInformation;
public object Clone()
{
Resume resume = new Resume(this._workInformation);
resume.age = this.age;
resume.sex = this.sex;
resume.name = this.name;
return resume;
}
}
这里面将workInformation
进行了深复制:把引用对象的变量指向复制过得新对象。而不是原有被引用过的对象。
private Resume(WorkInformation workInformation)
{
_workInformation = (ConsoleApp.WorkInformation) workInformation.Clone();
}
public object Clone()
{
Resume resume = new Resume(this._workInformation);
resume.age = this.age;
resume.sex = this.sex;
resume.name = this.name;
return resume;
}
本想比较两者之间的引用地址,c#这块需要自己写类方法所以便没有再判断。不过这个应该是c++中的值引用定义一样,复制的值指针指向他的地址,所以后续的值将会被覆盖。需要重新新建一个内存地址存储相应的值。(这个在我使用C++编写程序的时候再进行求证)
模板方法模式
模板方法模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
抽象方法需要定义一个抽象类并将一些不需要更改的内容写入,比如下面示例的测试题目,将需要修改的部分修改为虚拟类,进行修改,如:下面示例中的答案
static void Main(string[] args)
{
TestPaperA tpa = new TestPaperA();
tpa.TestQuestion1();
TestPaperB tpb = new TestPaperB();
tpb.TestQuestion1();
Console.ReadLine();
}
public class TemplateMethod
{
public void TestQuestion1()
{
Console.WriteLine("第一个题目的答案为:A:a,B:b,C:c,D:d");
Console.WriteLine("answer:{0}",Answer1());
}
protected virtual string Answer1()
{
return "";
}
}
class TestPaperA:TemplateMethod
{
protected override string Answer1()
{
return "A";
}
}
class TestPaperB:TemplateMethod
{
protected override string Answer1()
{
return "C";
}
}
迪米特法则
迪米特法则(LoD),也称:最少知识法则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某个方法,可以通过第三者转发这个调用。
外观模式(Facade)
外观模式(Facade):为系统中一组接口提供一个一致的界面。此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
这一设计模式适用于一个程序前期对于后期梳理不清或后期需要再原有重要方法之外拓展新的方法
code:
//Facade
Facade facade = new Facade();
facade.MethodA();
public class Facade
{
private SubSymbolOne _symbolOne;
private SubSymbolTwo _symbolTwo;
private SubSymbolThree _symbolThree;
private SubSymbolFour _symbolFour;
public Facade()
{
_symbolOne = new SubSymbolOne();
_symbolTwo = new SubSymbolTwo();
_symbolThree = new SubSymbolThree();
_symbolFour = new SubSymbolFour();
}
public void MethodA()
{
_symbolOne.MethodOne();
_symbolTwo.MethodTwo();
_symbolFour.MethodFour();
}
public void MethodB()
{
_symbolThree.MethodThree();
}
}
class SubSymbolOne
{
public void MethodOne()
{
Console.WriteLine("子系统方法一");
}
}
class SubSymbolTwo
{
public void MethodTwo()
{
Console.WriteLine("子系统方法二");
}
}
class SubSymbolThree
{
public void MethodThree() => Console.WriteLine("子系统方法三");
}
class SubSymbolFour
{
public void MethodFour() => Console.WriteLine("子系统方法四");
}
建造者模式(Builder)
**建造者模式(Builder)**将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
更契合土木领域的话可以这么理解:结构模型,不论是计算模型还是BIM模型或是其他三维模型都可分为墙梁板柱四个大类,通过规定每个格式的模型中每个类别的创建方式并通过最后一个控制器进行控制生成所有或者生成单独几个类别
code:
ConcreteBuilder1 builder1 = new ConcreteBuilder1();//建造者1
ConcreteBuilder2 builder2 = new ConcreteBuilder2();//建造者2
Director dir= new Director();//初始化指挥
dir.Construe(builder1);//传入建造者创建指定部件
var product1 = builder1.GetResult();
dir.Construe(builder2);
var product2 = builder2.GetResult();
product2.Show();
product1.Show();
/*
* 抽象建造类,确定部件有几部分组成
* 并生命一个活的结果的办法
*/
abstract class Builder
{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
}
class Product
{
IList<string> parts = new List<string>();
public void Add(string part)
{
parts.Add(part);
}
public void Show()
{
Console.WriteLine("产品的结果是:\n");
foreach (var part in parts)
{
Console.WriteLine(part);
}
}
}
class ConcreteBuilder1:Builder
{
private Product _product = new Product();
public override void BuildPartA()
{
_product.Add("MethodA");
}
public override void BuildPartB()
{
_product.Add("MethodB");
}
public override Product GetResult()
{
return _product;
}
}
class ConcreteBuilder2:Builder
{
private Product _product = new Product();
public override void BuildPartA()
{
_product.Add("MethodC");
}
public override void BuildPartB()
{
_product.Add("MethodD");
}
public override Product GetResult()
{
return _product;
}
}
class Director
{
public void Construe(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
观察者模式(Observer)
观察者模式又叫做发布-订阅模式定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够更新自己(这个更像是在WPF中用到的或是INotifyChange接口)
code:
ConcreteSubject subject = new ConcreteSubject();
subject.Attach(new ConcreteObserver("X",subject));
subject.Attach(new ConcreteObserver("Y",subject));
ConcreteSubject subject2 = new ConcreteSubject();
subject2.Attach(new ConcreteObserver("Z",subject2));
subject.Update+=new SubjectHandler(new ConcreteObserver("X",subject).Update);
subject.Update+=new SubjectHandler(new ConcreteObserver("Y",subject).Update);
subject2.Update+=new SubjectHandler(new ConcreteObserver("Z",subject2).Update);
subject.SubjectState = "is subject";
subject.Notify();
subject2.SubjectState = "is subject2";
subject2.Notify();
//观察者模式
abstract class Observer
{
public abstract void Update();
}
/*
* 通知类
* 增加或移除观察者
* 最终通过Notify方法输出结果
* 使用委托时,增加或移除观察者类可以取消
*/
delegate void SubjectHandler();//声明委托
abstract class OSubject
{
private IList<Observer> _observers = new List<Observer>();
public event SubjectHandler Update;//创建委托类Update
//增加观察者
public void Attach(Observer observer)
{
_observers.Add(observer);
}
//移除观察者
public void Detach(Observer observer)
{
_observers.Remove(observer);
}
//通知
public void Notify()
{
Update();//调用委托
// foreach (var observer in _observers)
// {
// observer.Update();
// }
}
}
/*
* 具体观察者,书中所讲老板或前台
* 增加角色本身的状态
*/
class ConcreteSubject : OSubject
{
private string subjectState;
public string SubjectState
{
get => subjectState;
set => subjectState = value;
}
}
/*
* 具体通知者,如书中所讲的摸鱼人员
*/
class ConcreteObserver:Observer
{
private string name;
private string observerState;
private ConcreteSubject concreteSubject;//具体通知者
public ConcreteObserver(string name, ConcreteSubject concreteSubject)
{
this.concreteSubject = concreteSubject;
this.name = name;
}
public override void Update()
{
observerState = ConcreteSubject.SubjectState;//获取统治者状态
Console.WriteLine("观察者{0}的新状态是{1}",name,observerState);
}
public ConcreteSubject ConcreteSubject
{
get => concreteSubject;
set => concreteSubject = value;
}
}
抽象工厂模式(AbstractFactory)
**抽象工厂模式(AbstractFactory)😗*提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类
看到书中的例子时,发现之前连接数据库学习的案例和抽象工厂模式非常相似,只不过我大部分时间只会连接一种数据库使用,通过将账户密码数据库类型存储在config
文件中并加密文件,读取配置文件中的密码达到数据保密防止重复输入密码的问题提高安全性,减少连接类和密码及部分语句之间的耦合性
如果数据库ORM与抽象工厂模式进行结合应该可以同时操作多个数据库,可以尝试一下
code:
const string dbName = "mysql";
User u = new User();
u.Name = "noName";
u.Id = 1;
AbstractFactory factory = new AbstractFactory();
var user = factory.CreateUser(dbName);
user.Insert(u);
class AbstractFactory
{
public IUser CreateUser(string symbol)
{
IUser result = null;
switch (symbol)
{
case "sql":
result = new SqlUser();
break;
case "mysql":
result = new MySqlUser();
break;
}
return result;
}
}
class User
{
private int _id;
public int Id
{
get => _id;
set => _id = value;
}
private string _name;
public string Name
{
get => _name;
set => _name = value;
}
}
/// <summary>
/// 插入用户
/// </summary>
interface IUser
{
void Insert(User user);
int GetUser(int id);
}
class SqlUser:IUser
{
public void Insert(User user)
{
Console.WriteLine("sql:insert database values {0}",user.Name);
}
public int GetUser(int id)
{
Console.WriteLine("sql:select name where id = {0}",id);
return - 1;
}
}
class MySqlUser:IUser
{
public void Insert(User user)
{
Console.WriteLine("mysql:insert database values {0}",user.Name);
}
public int GetUser(int id)
{
Console.WriteLine("mysql:select name where id = {0}",id);
return - 1;
}
}
第16章 状态模式
状态模式(State):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
- “状态模式主要解决的是当控制一个对象状态对象转换的条件表达式过于复杂时。把状态的逻辑转移到不同状态的一系列类中,可以把复杂的判断逻辑简化”–这个模式如果应用在Revit二次开发中,可以参考如果线段处于坐标系的四个象限中,可以通过角度进行分隔状态从而进行自动判断
- **状态模式的好处:**将于特定状态相关的行为局部化,并且将不同状态行为分割开来
- 当一个独享的行为取决于它的状态,并且它必须在运行时时刻根据状态改变它的行为时,就可以考虑状态模式了
- code:
static void Main(string[] args)
{
Content c = new Content(new ConcreteStateA());
c.Request();
c.Request();
c.Request();
c.Request();
Console.Read();
}
//状态模式
abstract class State
{
public abstract void Handle(Content content);
}
class ConcreteStateA:State
{
public override void Handle(Content content)
{
content.State=new ConcreteStateB();
}
}
class ConcreteStateB:State
{
public override void Handle(Content content)
{
content.State=new ConcreteStateA();
}
}
internal class Content
{
private State _state;
public Content(State state)
{
this._state = state;
}
public State State
{
get => _state;
set { _state = value; Console.WriteLine("当前状态:"+_state.GetType().Name);}
}
public void Request()
{
_state.Handle(this);
}
}
//example
abstract class EState
{
public abstract void WriteProgram(Work work);
}
class Work
{
private EState _state;
public Work(EState state)
{
_state = state;
}
private double _hour;
public double Hour
{
get => _hour;
set => _hour = value;
}
private bool _finish;
public bool Finish
{
get => _finish;
set => _finish = value;
}
public void SetState(EState state) => _state = state;//更换状态
public void WriteProgram() => _state.WriteProgram(this);
}
class ForenoonState:EState
{
public override void WriteProgram(Work work)
{
if (work.Hour < 12)
Console.WriteLine("当前时间:{0}点 上午工作,精神百倍", work.Hour);
else
work.SetState(new NoonState()); work.WriteProgram();
}
}
class NoonState:EState
{
public override void WriteProgram(Work work)
{
if(work.Hour<13)
Console.WriteLine("当前时间: {0}点 午休,犯困");
else
work.SetState(new AfternoonState());
}
}
class AfternoonState:EState
{
public override void WriteProgram(Work work)
{
if (work.Finish)
work.SetState(new ResetState());
else
Console.WriteLine("加班!");
}
}
class ResetState:EState
{
public override void WriteProgram(Work work)
{
Console.WriteLine("当前时间: {0} 点,下班回家");
}
}
第十七章 适配器模式
看这一章的标题首先会想到if...end if...
通过预编译进行不同版本之间的控制。
**适配器模式(Adapter):**将一个类的接口转换成客户希望的另一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。
我们在类中使用数据库数据时,会将数据库数据存储到DataSet中进操作Adapter.Fill
code:
static void Main(string[] args)
{
Target target = new Adapter();
target.Request();
Console.Read();
}
class Target
{
public virtual void Request()
{
Console.WriteLine("普通请求");
}
}
class Adaptee
{
public void SpecificRequest() => Console.WriteLine("特殊请求");
}
class Adapter:Target
{
private Adaptee _adaptee = new Adaptee();
public override void Request()
{
_adaptee.SpecificRequest();
}
}
第十八章 备忘录模式
**备忘录模式(Memento):**在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将对该对象族复制到原先保存的状态
code:
static void Main(string[] args)
{
//创建组织者,并赋值
Originator originator = new Originator();
originator.State = "On";
originator.Show();
//创建管理者,并存储备忘录
Caretaker caretaker = new Caretaker();
caretaker.Memento = originator.CreateMemento();
//修改组织者的值
originator.State = "Off";
originator.Show();
//还原为初始值
originator.SetMemento(caretaker.Memento);
originator.Show();
}
//备忘录,负责存储Originator对象的内部状态,病防治其他对象访问备忘录Memeneto
public class Memento
{
private string _state;
public Memento(string state)
{
_state = state;
}
public string State
{
get => _state;//仅能够获取状态
}
}
class Originator//发起人,创建一个备忘录Memento,用来记录当前时刻它的内部状态,并能回复状态
{
private string _state;
public string State
{
get => _state;
set { _state = value; }
}
public Memento CreateMemento()
{
return new Memento(_state);
}
public void SetMemento(Memento memento)
{
_state = memento.State;
}
public void Show() => Console.WriteLine("State: " + _state);
}
//管理者,存储备忘录,但是不能对备忘录进行修改或操作
class Caretaker
{
private Memento _memento;
public Memento Memento
{
get => _memento;
set => _memento = value;
}
}
第十九章 组合模式
**组合模式(Composite)😗*讲对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的试用具有一致性
- 透明模式:也就是在Component中声明所有用来管理子对象的方法,其中包括Add,Remove等方法,这样实现Component接口的所有用来管理子类对象的方法。这样做的好处就是叶节点和枝节点对于外界没有区别,他们具有一致对的行为接口。但是对于叶节点本身来说,它本身不具备Add,Remove的行为,所以接口是没有意义的
- 安全模式:在Component中不去声明Add和Remove方法,那么Leaf(叶节点)也就不需要实现它,而是在枝节点(ConpoenentSite)中进行声明用来管理子类对象的方法。这种模式需要客户端调用时做相应的判断,带来了不便
Xml或TreeView层级结构
code:
static void Main(string[] args)
{
Composite site = new Composite("root");
site.Add(new Leaf("Leaf A"));
site.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
site.Add(comp);
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
site.Add(new Leaf("Leaf C"));
Leaf leaf = new Leaf("Leaf D");
site.Add(leaf);
site.Display(1);
Console.Read();
}
class Composite:CComponent
{
private IList<CComponent> children = new List<CComponent>();
public Composite(string name) : base(name)
{
}
public override void Add(CComponent c)
{
children.Add(c);
}
public override void Remove(CComponent c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine((new string('-',depth))+name);
foreach (CComponent child in children)
{
child.Display(depth+2);
}
}
}
abstract class CComponent
{
protected string name;
public CComponent(string name) => this.name = name;
public abstract void Add(CComponent c);
public abstract void Remove(CComponent c);
public abstract void Display(int depth);
}
class Leaf:CComponent
{
public Leaf(string name) : base(name)
{
}
public override void Add(CComponent c)
{
Console.WriteLine("cannot add to a leaf");
}
public override void Remove(CComponent c)
{
Console.WriteLine("cannot remove a leaf");
;
}
public override void Display(int depth)
{
Console.WriteLine(new string('-',depth)+name);
}
}
第二十章 迭代器模式
接口: Ienumerator
C++ 中使用 c.begin()–>c.end()可以创建一个属于C++的迭代器
第二十一章 单例模式
**单例模式(Singlton):**保证一个类仅有一个实例,并提供一个访问它的全局变量
- 通常我们可以让一个全局变量使得一个对象被访问,但它不能当值你实例化多个对象。一个最高的办法就是,让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例方法
- 饿汉式单例类:在被加载时就将自己实例化
- 懒汉式单例类:在第一次被引用时,才会将自己实例化
code"
static void Main(string[] args)
{
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
if (s1 == s2)
{
Console.WriteLine("两个对象是相同的实例");
}
Console.Read();
}
class Singleton
{
private static Singleton instance;
private static readonly object syncRoot = new object();
private Singleton(){}
public static Singleton GetInstance()
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
第二十二章 桥接模式
桥接模式(Bridge): 将抽象部分与他的实现部分分离,使它们可以独立地变化
- 合成/聚合复用原则(CARP):尽量使用合成/聚合,尽量不要使用类聚合
code:
static void Main(string[] args)
{
//Bridge
Abstraction abstraction = new RefinedAbstraction();
abstraction.SetImplementor(new ConcreteImplementorA());
abstraction.Operator();
abstraction.SetImplementor(new ConcreteImplementorB());
abstraction.Operator();
Console.Read();
}
/*
* 桥接模式
*/
public class Bridge
{
}
abstract class Implementor
{
public abstract void Operator();
}
class ConcreteImplementorA:Implementor
{
public override void Operator()
{
Console.WriteLine("具体实现方法A的方法执行");
}
}
class ConcreteImplementorB:Implementor
{
public override void Operator()
{
Console.WriteLine("具体实现方法B的方法执行");
}
}
class Abstraction
{
protected Implementor _implementor;
public void SetImplementor(Implementor implementor)
{
this._implementor = implementor;
}
public virtual void Operator()
{
_implementor.Operator();
}
}
class RefinedAbstraction:Abstraction
{
public override void Operator()
{
_implementor.Operator();
}
}
第二十三章 命令模式
命令模式(Command): 将一个请求封装为对象,从而是你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作
- 他能较容易的设计一个命令队列
- 在需要的情况下,可以将命令计入日志
- 允许接收请求的一方决定是否否决请求
- 可以容易的实现对请求的撤销和重做
- 由于加进新的命令类不影响其他的类,因此增加新的具体命令类很容易
code:
static void Main(string[] args)
{
//Command
Receiver re = new Receiver();
Command c = new ConcreteCommand(re);
Invoker i = new Invoker();
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
abstract class Command
{
protected Receiver _receiver;
public Command(Receiver receiver) => _receiver = receiver;
abstract public void Execute();
}
class ConcreteCommand:Command
{
public ConcreteCommand(Receiver receiver) : base(receiver)
{
}
public override void Execute()
{
_receiver.Action();
}
}
class Invoker
{
private Command _command;
public void SetCommand(Command command)
{
_command = command;
}
public void ExecuteCommand()
{
_command.Execute();
}
}
class Receiver
{
public void Action()
{
Console.WriteLine("执行请求");
}
}
职责链模式
职责链模式(Chain of Reponsibility): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递请求,知道一个对象处理他为止
- 当客户提交一个请求时,请求时沿链传递直至有一个ConcreteHandler对象负责处理它。
- 接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,他们仅需要保持一个指向其后继者的引用,而不需要保持所有的候选者引用
- 随时的增加或修改处理一个请求的结构,增强了给对象指派职责的灵活性
- 需要考虑在结尾末端的处理方式
code:
static void Main(string[] args)
{
//ChainOfResponsibility
ConcreteHandler handle1 = new ConcreteHandler();
ConcreteHandlerB handle2 = new ConcreteHandlerB();
ConcreteHandlerC handle3 = new ConcreteHandlerC();
handle1.SetChainOfResponsilbility(handle2);
handle3.SetChainOfResponsilbility(handle3);
int[] resquests = {2, 5, 14, 22, 18, 3, 27, 20};
foreach (var i in resquests)
{
handle1.HandlerRequest(i);
}
}
abstract class ChainOfResponsibilty
{
protected ChainOfResponsibilty successor;
public void SetChainOfResponsilbility(ChainOfResponsibilty chainOfResponsibilty)
{
successor = chainOfResponsibilty;
}
public abstract void HandlerRequest(int request);
}
class ConcreteHandler:ChainOfResponsibilty
{
public override void HandlerRequest(int request)
{
if (request>=0&& request<10)
{
Console.WriteLine("{0} 处理请求 {1}",this.GetType().Name,request);
}
else if (successor != null)
{
successor.HandlerRequest(request);
}
}
}
class ConcreteHandlerB:ChainOfResponsibilty
{
public override void HandlerRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine("{0} 处理请求 {1}",this.GetType().Name,request);
}
else if(successor !=null)
{
successor.HandlerRequest(request);
}
}
}
class ConcreteHandlerC:ChainOfResponsibilty
{
public override void HandlerRequest(int request)
{
if (request > 20 && request < 30)
{
Console.WriteLine("{0} 处理请求 {1}",this.GetType().Name,request);
}
else if (successor != null)
{
successor.HandlerRequest(request);
}
}
}
第二十五章 中介者模式
**中介者模式(Mediator)😗*用一个中介者对象来封装一系列对象的交互。中介者使个对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- 中介者模式很容易在系统中应用,也很容易在系统中误用,当系统出现了“多对多”交互复杂的对象群时,不要急于使用中介者模式,而是要反思你的系统在设计上是否合理。
- 由于把对象如何协作进行了抽象,将中介作为一个堵路的概念,并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统
- 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合;以及想定制一个分布在多个类中的行为,而不像生成太多子类的场合
code:
static void Main(string[] args)
{
ConcreteMediator m = new ConcreteMediator();
ConcreteColleague c1 = new ConcreteColleague(m);
ConcreteColleague2 c2 = new ConcreteColleague2(m);
m.Colleague1 = c1;
m.Colleague2 = c2;
c2.Send("吃过饭了,你那?");
c1.Send("没有那,一起?");
}
abstract class Mediator
{
public abstract void Send(string message,Colleague colleague);
}
abstract class Colleague
{
protected Mediator _mediator;
public Colleague(Mediator mediator) => _mediator = mediator;
}
class ConcreteMediator:Mediator
{
private ConcreteColleague _colleague1;
private ConcreteColleague2 _colleague2;
public ConcreteColleague Colleague1
{
set => _colleague1 = value;
}
public ConcreteColleague2 Colleague2
{
set => _colleague2 = value;
}
public override void Send(string message, Colleague colleague)
{
if (colleague == _colleague1)
{
_colleague2.Notify(message);
}
else
{
_colleague1.Notify(message);
}
}
}
class ConcreteColleague:Colleague
{
public ConcreteColleague(Mediator mediator) : base(mediator)
{
}
public void Send(string message)
{
_mediator.Send(message,this);
}
public void Notify(string message)
{
Console.WriteLine("同事1得到的信息是: "+ message);
}
}
class ConcreteColleague2:Colleague
{
public ConcreteColleague2(Mediator mediator) : base(mediator)
{
}
public void Send(string message)
{
_mediator.Send(message,this);
}
public void Notify(string message)
{
Console.WriteLine("同事2得到的信息是: "+message);
}
}
第二十六章 享元模式
享元模式(FlyWeight): 运用共享技术有效地支持大量细粒度的对象
- 如果一个应用程序使用了大量的对象,而大量的对这些对象造成很大的存储开销时就应该考虑使用,还有就是对象的多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以使用享元模式
code:
static void Main(string[] args)
{
//FlyWeight
int i = 22;
FlyWeightFactory f = new FlyWeightFactory();
FlyWeight fx = f.GetFlyWeight("X");
fx.Operation(--i);
FlyWeight fy = f.GetFlyWeight("Y");
fy.Operation(--i);
FlyWeight fz = f.GetFlyWeight("Z");
fz.Operation(--i);
FlyWeight uf = new UnSharedConcreteFlyWeight();
uf.Operation(--i);
}
abstract class FlyWeight
{
public abstract void Operation(int exterinsicatae);
}
class ConcreteFlyWeight:FlyWeight
{
public override void Operation(int exterinsicatae)
{
Console.WriteLine("具体FlyWeight: "+exterinsicatae);
}
}
class UnSharedConcreteFlyWeight:FlyWeight
{
public override void Operation(int exterinsicatae)
{
Console.WriteLine("不共享的具体FlyWeight: " + exterinsicatae);
}
}
class FlyWeightFactory
{
private Hashtable flyWeights = new Hashtable();
public FlyWeightFactory()
{
flyWeights.Add("X",new ConcreteFlyWeight());
flyWeights.Add("Y",new ConcreteFlyWeight());
flyWeights.Add("Z",new ConcreteFlyWeight());
}
public FlyWeight GetFlyWeight(string key)
{
return (FlyWeight) flyWeights[key];
}
}
第二十七章 解释器模式
解释器模式(Interpreter): 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示解释语言中的句子
- 如果一种特定类型的问题发生的频率足够高,那么可能值得将该问题的各个实例表述为一个简单语言的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决问题
code:
static void Main(string[] args)
{
IContext context = new IContext();
List<AbstractExpression> list = new List<AbstractExpression>();
list.Add(new NonterminalExpression());
list.Add(new TerminalExpression());
list.Add(new TerminalExpression());
foreach (var expression in list)
{
expression.Interpret(context);
}
}
abstract class AbstractExpression
{
public abstract void Interpret(IContext context);
}
class NonterminalExpression:AbstractExpression
{
public override void Interpret(IContext context)
{
Console.WriteLine("非终端解释器");
}
}
class TerminalExpression:AbstractExpression
{
public override void Interpret(IContext context)
{
Console.WriteLine("终端解释器");
}
}
class IContext
{
private string _input;
public string Input
{
get => _input;
set => _input = value;
}
private string _output;
public string Output
{
get => _output;
set => _output = value;
}
}
访问者模式
访问者模式(Visitor): 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作
- 访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化
- 访问者模式的目的是把数据处理从数据结构中分离出来,比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得更容易
- 访问者模式的有点就是增加新的操作很容易,因为增加新的操作就意味增加一个新的访问者,访问者模式将有关的行为集中到一个行为对象中
code:
static void Main(string[] args)
{
ObjectStructure structure = new ObjectStructure();
structure.Attach(new ConcreteElementA());
structure.Attach(new ConcreteElementB());
ConcreteVisitor v1 = new ConcreteVisitor();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
structure.Accept(v1);
structure.Accept(v2);
}
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
}
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
class ConcreteElementA:Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementA(this);
}
public void OperationA()
{
}
}
class ConcreteElementB:Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementB(this);
}
public void OperationB()
{
}
}
class ConcreteVisitor:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementA.GetType().Name,this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementB.GetType().Name,this.GetType().Name);
}
}
class ConcreteVisitor2:Visitor
{
public override void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementA.GetType().Name,this.GetType().Name);
}
public override void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} 被 {1} 访问",concreteElementB.GetType().Name,this.GetType().Name);
}
}
class ObjectStructure
{
private IList<Element> elements = new List<Element>();
public void Attach(Element element)
{
elements.Add(element);
}
public void Detach(Element element)
{
elements.Remove(element);
}
public void Accept(Visitor visitor)
{
foreach (var element in elements)
{
element.Accept(visitor);
}
}