1 设计原则
开闭原则
对扩展开放,对修改关闭
对可变性进行封装
抽象化是关键
里氏代换原则
任何基类可以出现的地方,子类一定可以出现
对开闭原则的补充
违反里氏代换原则,则必然违反开闭原则,反之不一定成立
依赖倒转原则
要依赖于抽象,不要依赖于实现
针对接口编程,不要针对实现编程
开闭原则是目标,依赖倒转是手段
合成/聚合复用原则
少用继承,多用合成/聚合
实现开闭原则的必要条件
迪米特法则
一个软件实体应该与尽可能少的其他实体发生相互作用
不会将修改的压力传递到其他模块
限制了通信的宽度和深度
提高了系统功能的扩展性
是一条通向开闭原则的道路
接口隔离原则
为客户端提供尽可能小的单独的接口,不要提供大的总的接口
限制的是通讯的宽度
不会讲修改的压力传递到其他的对象
一:简单工厂模式
从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法模式。可以解决对象创建问题。
public class Operation
{
private double _numberA = 0;
private double _numberB = 0;
public virtual double GetResult()
{
}
}
class OperationAdd : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA + NumberB;
return result;
}
}
class OperationSub : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
public class OperationFactory
{
public static Operation createOperate(string operate)
{
Operation oper = null; //关联关系,需要知道Operation类,而不需要依赖
switch (operate)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
}
return oper;
}
}
二:策略模式:在不同时间运用不用的业务规则。
定义算法家族,分别封装起来,让他们之间可以相互替换,而且此模式让算法的变化不会影响到使用算法的客户。
比如,超市收款机,有正常付款,有打折,也有让利(买多少返多少),而打折和让利是会随时间变化的,即这个算法是时常变动的。这个如果用工厂模式的话,需要为每种算法创建实例,而且算法会变,每变一次,都需要重新编译程序。
关键注意点:算法只是一种策略。
抽象算法类
abstract class Strategy
{
算法方法
public abstract void AlgorithmInterface();
}
具体算法A
class ConcreteStrategyA : Strategy
{
算法A实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法A实现");
}
}
具体算法B
class ConcreteStrategyB : Strategy
{
算法B实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法B实现");
}
}
具体算法C
class ConcreteStrategyC : Strategy
{
算法C实现方法
public override void AlgorithmInterface()
{
Console.WriteLine("算法C实现");
}
}
上下文
class Context
{
Strategy strategy;
public Context(Strategy strategy) //传入相应策略,根据多态进行动态处理
{
this.strategy = strategy;
}
上下文接口
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
Context context;
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
context = new Context(new ConcreteStrategyC());
context.ContextInterface();
三:策略模式和简单工厂模式结合,即创建对象时用工厂模式(工厂模式的弊端可以借助反射),然后在执行相应算法时,用策略模式。
对于上面的算法,由用户来判断,并进行创建。
而这些操作可以一入到Context中,即只需要传一个可以进行识别的类型进来即可,而无需传入类。
class Context
{
Strategy strategy;
public Context(String type) //工厂模式
{
switch(type)//此处SWITCH的增加,会导致,当需要增加新的算法时,需要修改此处代码,有需求就有变化,这里设计到改动需求的代价问题,可以考虑使用反射技术
{
case "A":
strategy = new ConcreteStrategyA();
break;
case "B":
strategy = new ConcreteStrategyB();
break;
case "C":
strategy = new ConcreteStrategyC();
break;
default:
break;
}
}
上下文接口
public void ContextInterface() //策略模式
{
把所有算法抽象出来,有各个子类具体实现
strategy.AlgorithmInterface();
}
}
这样在使用时,可以直接这样调用
context = new Context(type);//工厂模式
context.ContextInterface();//策略模式
四:反射:可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
class Context
{
private Strategy strategy;
public void setBehavior(Strategy strategy)
{
this.strategy = strategy;
}
上下文接口
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
Context context = new Context();
这样的话,可以在配置文件里面修改,而客户端和Context面都无需用到SWITCH了。
context.setBehavior("更加操作类型反推实例,CreateInstance");
context.ContextInterface();
五:装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
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 SetComponent(Component component)//关键,给某个对象进行装饰
{
this.component = component;
}
public override void Operation()
{
if (component != null)
{
component.Operation();
}
}
}
class ConcreteDecoratorA : Decorator
{
private string addedState;
public override void Operation()
{
base.Operation();//先执行基类
addedState = "New State";
Console.WriteLine("具体装饰对象A的操作");
}
}
class ConcreteDecoratorB : Decorator
{
public override void Operation()
{
base.Operation();//先执行基类
AddedBehavior();
Console.WriteLine("具体装饰对象B的操作");
}
private void AddedBehavior()
{
}
}
调用:ConcreteComponent c = new ConcreteComponent(); //先弄好对那个对象进行装饰
ConcreteDecoratorA d1 = new ConcreteDecoratorA();//需要装饰的物件
ConcreteDecoratorB d2 = new ConcreteDecoratorB();
下面时装饰过程
d1.SetComponent(c);//将D1装饰到对象上
d2.SetComponent(d1);//在装饰D1的对象上装饰D2
d2.Operation();//c.operateion-->d1.operation-->d2.operation
六:代理模式:为其他对象提供代理以控制对这个对象的访问。
class Program
{
static void Main(string[] args)
{
Proxy proxy = new Proxy();
proxy.Request();
Console.Read();
}
}
abstract class Subject
{
public abstract void Request();
}
class RealSubject : Subject//实际对象干活
{
public override void Request()
{
Console.WriteLine("真实的请求");
}
}
class Proxy : Subject
{
RealSubject realSubject; //真实的对象
public override void Request()
{
if (realSubject == null)
{
realSubject = new RealSubject();
}
realSubject.Request();//让代理干活,而代理交给了真实的对象
}
}
七:工厂模式:定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
简单工厂:最大有点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,对于客户端来说,祛除了于具体产品的依赖,但是CASE不但对扩展开发了,还对修改也开放了。
工厂模式:把CASE的选择移到了客户端来。
<summary>
运算类
</summary>
class Operation
{
private double _numberA = 0;
private double _numberB = 0;
public virtual double GetResult()
{
double result = 0;
return result;
}
}
class OperationAdd : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA + NumberB;
return result;
}
}
class OperationSub : Operation
{
public override double GetResult()
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
interface IFactory
{
Operation CreateOperation();
}
class AddFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationAdd();
}
}
class SubFactory : IFactory
{
public Operation CreateOperation()
{
return new OperationSub();
}
}
简单工厂通过CASE实现
工厂模式则把逻辑判断移到了客户端,由客户端决定(利用反射可以解决)
调用:
IFactory operFactory = new AddFactory();//由子类决定实例化那个类
Operation oper = operFactory.CreateOperation();
oper.NumberA = 1;
oper.NumberB = 2;
double result=oper.GetResult();
八:原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
class Resume : ICloneable
{
private string name;
private string sex;
private string company;
public Resume(string name)
{
this.name = name;
}
设置个人信息
public void SetPersonalInfo(string sex, string age)
{
this.sex = sex;
}
设置工作经历
public void SetWorkExperience(string timeArea, string company)
{
this.company = company;
}
显示
public void Display()
{
Console.WriteLine("{0} {1}", name, sex);
Console.WriteLine("工作经历:{0}", company);
}
public Object Clone()
{
浅复制,针对引用情况,需要改成深复制
return (Object)this.MemberwiseClone();
}
}
调用:
Resume a = new Resume("大鸟");
a.SetPersonalInfo("男", "29");
a.SetWorkExperience("1998-2000", "XX公司");
Resume b = (Resume)a.Clone();
b.SetWorkExperience("1998-2006", "YY企业");
Resume c = (Resume)a.Clone();
c.SetPersonalInfo("男", "24");
a.Display();
b.Display();
c.Display();
九:模板方法模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。该方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
把不变的行为搬到超类,去除子类中的重复代码来体现其优势。
class Program
{
static void Main(string[] args)
{
AbstractClass c;
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
}
}
abstract class AbstractClass
{
算法的特定步骤
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
总的一样,可以复用
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("");
}
}
class ConcreteClassA : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类A方法1实现");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("具体类A方法2实现");
}
}
class ConcreteClassB : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("具体类B方法1实现");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("具体类B方法2实现");
}
}
十:外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
class Program
{
static void Main(string[] args)
{
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();
Console.Read();
}
}
四个独立的子系统,他们之间的通讯由外观模式FACADE来组织
class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" 子系统方法一");
}
}
class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" 子系统方法二");
}
}
class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" 子系统方法三");
}
}
class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" 子系统方法四");
}
}
class Facade
{
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four;
public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
}
public void MethodA()
{
Console.WriteLine("/n方法组A() ---- ");
one.MethodOne();
two.MethodTwo();
four.MethodFour();
}
public void MethodB()
{
Console.WriteLine("/n方法组B() ---- ");
two.MethodTwo();
three.MethodThree();
}
}
十一:建造者模式:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。
使用建造模式,用户只需指定需要建造的类型就可以得到它们,而具体建造过程和细节就不需知道。
当创建复杂对象的算法应该独立该对象的组成部分以及它们的装配方式时适用。
class Program
{
static void Main(string[] args)
{
Director director = new Director();
Builder b1 = new ConcreteBuilder1();
Builder b2 = new ConcreteBuilder2();
director.Construct(b1);
Product p1 = b1.GetResult();
p1.Show();
director.Construct(b2);
Product p2 = b2.GetResult();
p2.Show();
Console.Read();
}
}
class Director
{
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
}
abstract class Builder
{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract Product GetResult();
}
class ConcreteBuilder1 : Builder
{
private Product product = new Product();
public override void BuildPartA()
{
product.Add("部件A");
}
public override void BuildPartB()
{
product.Add("部件B");
}
public override Product GetResult()
{
return product;
}
}
class ConcreteBuilder2 : Builder
{
private Product product = new Product();
public override void BuildPartA()
{
product.Add("部件X");
}
public override void BuildPartB()
{
product.Add("部件Y");
}
public override Product GetResult()
{
return product;
}
}
class Product
{
IList<string> parts = new List<string>();
public void Add(string part)
{
parts.Add(part);
}
public void Show()
{
Console.WriteLine("/n产品 创建 ----");
foreach (string part in parts)
{
Console.WriteLine(part);
}
}
}
十二:观察者模式:定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题。
这个主题对象的状态发生变化时,会通知所有观察者对象,是他们能够自动更新自己。
及接触耦合,让耦合的双方都依赖于对象,而不是依赖于具体.从而使得各自的变化都不会影响另一边的变化
下面有两个模型,一个是通知到跑去告诉观察者,有情况的话通知他.另一个是由通知者自己决定有情况时通知那些人.
static void Main(string[] args)
{
老板胡汉三
Boss huhansan = new Boss();
看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
看NBA的同事
NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);
huhansan.Attach(tongshi1);
huhansan.Attach(tongshi2);
huhansan.Detach(tongshi1);
老板回来
huhansan.SubjectState = "我胡汉三回来了!";
发出通知
huhansan.Notify();
Console.Read();
}
通知者接口
interface Subject
{
void Attach(Observer observer);
void Detach(Observer observer);
void Notify();
string SubjectState
{
get;
set;
}
}
class Secretary : Subject
{
同事列表
private IList<Observer> observers = new List<Observer>();
private string action;
增加
public void Attach(Observer observer)//依赖抽象,而非具体
{
observers.Add(observer);
}
减少
public void Detach(Observer observer)//依赖抽象,而非具体
{
observers.Remove(observer);
}
通知
public void Notify()
{
foreach (Observer o in observers)//依赖抽象,而非具体
o.Update();
}
前台状态
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
class Boss : Subject
{
同事列表
private IList<Observer> observers = new List<Observer>();
private string action;
增加
public void Attach(Observer observer)
{
observers.Add(observer);
}
减少
public void Detach(Observer observer)
{
observers.Remove(observer);
}
通知
public void Notify()
{
foreach (Observer o in observers)
o.Update();
}
老板状态
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
抽象观察者
abstract class Observer
{
protected string name;
protected Subject sub;
public Observer(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
public abstract void Update();
}
看股票的同事
class StockObserver : Observer
{
public StockObserver(string name, Subject sub)
: base(name, sub)
{
}
public override void Update()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name);
}
}
看NBA的同事
class NBAObserver : Observer
{
public NBAObserver(string name, Subject sub)
: base(name, sub)
{
}
public override void Update()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}
如果观察者和通知者之间互相不知道,有客户端来决定通知谁.
class Program
{
static void Main(string[] args)
{
老板胡汉三
Boss huhansan = new Boss();
看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
看NBA的同事
NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);
一个委托可以搭载多个方法,而且这些方法并不需要属于同一个类
但是同一个委托搭载的多个方法必须有相同的原形和形式,即相同的参数列表和返回值
huhansan.Update += new EventHandler(tongshi1.CloseStockMarket);
huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);
老板回来
huhansan.SubjectState = "我胡汉三回来了!";
发出通知
huhansan.Notify();
Console.Read();
}
}
通知者接口
interface Subject//不需要ADD,和DETACH接口了
{
void Notify();
string SubjectState
{
get;
set;
}
}
事件处理程序的委托
delegate void EventHandler();
class Secretary : Subject
{
声明一事件Update,类型为委托EventHandler
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
class Boss : Subject
{
声明一事件Update,类型为委托EventHandler
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
看股票的同事
class StockObserver
{
private string name;
private Subject sub;
public StockObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
关闭股票行情
public void CloseStockMarket()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name);
}
}
看NBA的同事
class NBAObserver
{
private string name;
private Subject sub;
public NBAObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
关闭NBA直播
public void CloseNBADirectSeeding()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}
十三:抽象工厂模式:提供一个创建一序列相关或相互依赖对象的接口,而无需指定它们具体的类。
class Program
{
static void Main(string[] args)
{
AbstractFactory factory1 = new ConcreteFactory1();
Client c1 = new Client(factory1);
c1.Run();
AbstractFactory factory2 = new ConcreteFactory2();
Client c2 = new Client(factory2);
c2.Run();
Console.Read();
}
}
abstract class AbstractFactory
{
public abstract AbstractProductA CreateProductA();
public abstract AbstractProductB CreateProductB();
}
class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA1();
}
public override AbstractProductB CreateProductB()
{
return new ProductB1();
}
}
class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA2();
}
public override AbstractProductB CreateProductB()
{
return new ProductB2();
}
}
abstract class AbstractProductA
{
}
abstract class AbstractProductB
{
public abstract void Interact(AbstractProductA a);
}
class ProductA1 : AbstractProductA
{
}
class ProductB1 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}
class ProductA2 : AbstractProductA
{
}
class ProductB2 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}
class Client
{
private AbstractProductA AbstractProductA;
private AbstractProductB AbstractProductB;
Constructor
public Client(AbstractFactory factory)
{
AbstractProductB = factory.CreateProductB();
AbstractProductA = factory.CreateProductA();
}
public void Run()
{
AbstractProductB.Interact(AbstractProductA);
}
}
十四:反射+简单工厂:所有用简单工厂的地方,都可以用反射技术来祛除switch 和 if,解除分支判断带来的耦合。
class Program
{
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
IUser iu = DataAccess.CreateUser();
iu.Insert(user);
iu.GetUser(1);
IDepartment id = DataAccess.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
Console.Read();
}
}
class User
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
class Department
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _deptName;
public string DeptName
{
get { return _deptName; }
set { _deptName = value; }
}
}
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
class SqlserverUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在Sqlserver中给User表增加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在Sqlserver中根据ID得到User表一条记录");
return null;
}
}
class AccessUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在Access中给User表增加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在Access中根据ID得到User表一条记录");
return null;
}
}
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
class SqlserverDepartment : IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在Sqlserver中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在Sqlserver中根据ID得到Department表一条记录");
return null;
}
}
class AccessDepartment : IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在Access中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在Access中根据ID得到Department表一条记录");
return null;
}
}
class DataAccess
{
private static readonly string AssemblyName = "抽象工厂模式";
private static readonly string db = ConfigurationManager.AppSettings["DB"];
public static IUser CreateUser()
{
string className = AssemblyName + "." + db + "User";
return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
}
public static IDepartment CreateDepartment()
{
string className = AssemblyName + "." + db + "Department";
return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className);
}
}
十五:状态模式:当一个对象内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
即当控制一个对象的状态转换条件过于复杂时,把状态的判断逻辑转移到表示不同状态的一序列类中,可以把复杂的判断逻辑简化。
class Program
{
static void Main(string[] args)
{
Context c = new Context(new ConcreteStateA());
c.Request();
c.Request();
c.Request();
c.Request();
Console.Read();
}
}
class Context
{
private State state;
public Context(State state)
{
this.state = state;
}
public State State
{
get
{
return state;
}
set
{
state = value;
Console.WriteLine("当前状态:" + state.GetType().Name);
}
}
public void Request()
{
state.Handle(this);
}
}
abstract class State
{
public abstract void Handle(Context context);
}
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
十六:适配器模式:将一个类的接口转换成客户需要的另一个接口
class Program
{
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();
//本来由Adapter做的事情,最后实际由Adaptee来做了
public override void Request()
{
adaptee.SpecificRequest();
}
}
十七:备忘录模式:在不破坏对象封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。
缺点:状态多而且需要完整的保存到备忘录对象中时,备份对象会非常消耗资源。
class Program
{
static void Main(string[] args)
{
Originator o = new Originator();
o.State = "On";
o.Show();
Caretaker c = new Caretaker();
c.Memento = o.CreateMemento();
o.State = "Off";
o.Show();
o.SetMemento(c.Memento);
o.Show();
Console.Read();
}
}
//负责创建和恢复
class Originator
{
private string state;
public string State
{
get { return 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 Memento
{
private string state;
public Memento(string state)
{
this.state = state;
}
public string State
{
get { return state; }
}
}
//管理备忘录
class Caretaker
{
private Memento memento;
public Memento Memento
{
get { return memento; }
set { memento = value; }
}
}
十八:组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象使用更具有一致性。
即:可以让客户可以一致的使用组合结构和单个对象。
abstract class Component
{
protected string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
class Composite : Component//树枝
{
private List<Component> children = new List<Component>();
public Composite(string name)
: base(name)
{ }
public override void Add(Component c)
{
children.Add(c);
}
public override void Remove(Component c)
{
children.Remove(c);
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
foreach (Component component in children)
{
component.Display(depth + 2);
}
}
}
class Leaf : Component//树叶
{
public Leaf(string name)
: base(name)
{ }
public override void Add(Component c)
{
Console.WriteLine("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
static void Main(string[] args)
{
Composite root = new Composite("root");//主干
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
root.Add(new Leaf("Leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
Console.Read();
}
十九:迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露该对象内部表示。(FOREACH)
abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
class ConcreteAggregate : Aggregate
{
private IList<object> items = new List<object>();
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
public int Count
{
get { return items.Count; }
}
public object this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
}
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
class ConcreteIterator : Iterator
{
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
public override object First()
{
return aggregate[0];
}
public override object Next()
{
object ret = null;
current++;
if (current < aggregate.Count)
{
ret = aggregate[current];
}
return ret;
}
public override object CurrentItem()
{
return aggregate[current];
}
public override bool IsDone()
{
return current >= aggregate.Count ? true : false;
}
}
class ConcreteIteratorDesc : Iterator
{
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIteratorDesc(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
current = aggregate.Count - 1;
}
public override object First()
{
return aggregate[aggregate.Count - 1];
}
public override object Next()
{
object ret = null;
current--;
if (current >= 0)
{
ret = aggregate[current];
}
return ret;
}
public override object CurrentItem()
{
return aggregate[current];
}
public override bool IsDone()
{
return current < 0 ? true : false;
}
}
static void Main(string[] args)
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "大鸟";
a[1] = "小菜";
a[2] = "行李";
a[3] = "老外";
a[4] = "公交内部员工";
a[5] = "小偷";
Iterator i = new ConcreteIterator(a);
//Iterator i = new ConcreteIteratorDesc(a);
object item = i.First();
while (!i.IsDone())
{
Console.WriteLine("{0} 请买车票!", i.CurrentItem());
i.Next();
}
Console.Read();
}
.NET已经将这些功能集合到了IEUMERATOR中
static void Main(string[] args)
{
IList<string> a = new List<string>();
a.Add("大鸟");
a.Add("小菜");
a.Add("行李");
a.Add("老外");
a.Add("公交内部员工");
a.Add("小偷");
foreach (string item in a)
{
Console.WriteLine("{0} 请买车票!", item);
}
IEnumerator<string> e = a.GetEnumerator();
while (e.MoveNext())
{
Console.WriteLine("{0} 请买车票!", e.Current);
}
Console.Read();
}
二十:单例模式
class Singleton
{
private static Singleton instance;
private Singleton() { }
public static Singleton GetInstance()
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
class Singleton//多线程
{
private static Singleton instance;
private static readonly object syncRoot = new object();
private Singleton() { }
public static Singleton GetInstance()
{
lock (syncRoot)//形象性能
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
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;
}
}
class Singleton//MSDN静态初始化
{
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton GetInstance()
{
return instance;
}
}
二十一:桥接模式:将抽象部分和实现分离,使他们都可以独立的变化。
class Abstraction
{
protected Implementor implementor;
public void SetImplementor(Implementor implementor)
{
this.implementor = implementor;
}
public virtual void Operation()
{
implementor.Operation();
}
}
class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
abstract class Implementor
{
public abstract void Operation();
}
class ConcreteImplementorA : Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现A的方法执行");
}
}
class ConcreteImplementorB : Implementor
{
public override void Operation()
{
Console.WriteLine("具体实现B的方法执行");
}
}
static void Main(string[] args)
{
Abstraction ab = new RefinedAbstraction();
ab.SetImplementor(new ConcreteImplementorA());
ab.Operation();
ab.SetImplementor(new ConcreteImplementorB());
ab.Operation();
Console.Read();
}
二十二:命令模式:将请求封装成对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。
重点:把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。
一:可以较容易的设计一个命令队列;
二:在需要的情况下,可以较容易的将命令记录日志;
三:允许接收请求的一方决定是否要否决请求;
四:可以容易的实现对请求的撤销和重做;
五:新加的命令不影响其他类。
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
abstract public void Execute();
}
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver)
:
base(receiver) { }
public override void Execute()
{
receiver.Action();
}
}
class Receiver
{
public void Action()
{
Console.WriteLine("执行请求!");
}
}
class Invoker
{
private Command command;
public void SetCommand(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
class Program
{
static void Main(string[] args)
{
Receiver r = new Receiver();//执行者
Command c = new ConcreteCommand(r);//实际的命令,服务员给指定厨师完成
Invoker i = new Invoker();//服务员
//从客户来说,只知道服务员,而不知道大厨,所以对于客户来说命令都是由服务员执行的
i.SetCommand(c);
i.ExecuteCommand();
Console.Read();
}
}
二十三:职责链模式:使多个对象都有机会处理请求,从而避免请求发送者和接受者之间的耦合关系。将这个对象建成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
只需要保持一个指向其后继的引用,而不用保持所有候选接受者的引用。
abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
class ConcreteHandler1 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("{0} 处理请求 {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine("{0} 处理请求 {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class ConcreteHandler3 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine("{0} 处理请求 {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
class Program
{
static void Main(string[] args)
{
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach (int request in requests)
{
h1.HandleRequest(request);
}
Console.Read();
}
}
二十四:中介者模式,用一个中介对象封装一序列的对象交互。使各个对象不需要显式的相互引用,从而使其耦合松散,而且可以独立改变他们之间的交互。
迪米特法则:如果两个类不必彼此通讯,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
缺点:过于集中控制使得中介者复杂。
abstract class Mediator
{
public abstract void Send(string message, Colleague colleague);
}
class ConcreteMediator : Mediator
{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public ConcreteColleague1 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);
}
}
}
abstract class Colleague
{
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}
class ConcreteColleague1 : Colleague
{
public ConcreteColleague1(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);
}
}
class Program
{
static void Main(string[] args)
{
ConcreteMediator m = new ConcreteMediator();
ConcreteColleague1 c1 = new ConcreteColleague1(m);
ConcreteColleague2 c2 = new ConcreteColleague2(m);
m.Colleague1 = c1;
m.Colleague2 = c2;
c1.Send("吃过饭了吗?");
c2.Send("没有呢,你打算请客?");
Console.Read();
}
}
二十五:享元模式:运用共享技术有效地支持大量细粒度对象。
class FlyweightFactory
{
private Hashtable flyweights = new Hashtable();
public Flyweight GetFlyweight(string key)
{
if (!flyweights.ContainsKey(key))
flyweights.Add(key, new ConcreteWebSite(key));
return ((Flyweight)flyweights[key]);
}
}
abstract class Flyweight
{
public abstract void Operation(int extrinsicstate);
}
class ConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("具体Flyweight:" + extrinsicstate);
}
}
class UnsharedConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("不共享的具体Flyweight:" + extrinsicstate);
}
}
static void Main(string[] args)
{
int extrinsicstate = 22;
FlyweightFactory f = new FlyweightFactory();
Flyweight fx = f.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy = f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz = f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();
uf.Operation(--extrinsicstate);
Console.Read();
}
}
二十六:解释器模式:给定一个语言,定义它的文法的一种表示。并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
即:如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
//罗马字符转换为十进制数字
//Ewindows xp ression抽象类:抽象表达式,声明一个抽象的解释器操作,这个抽象类为抽象语法树中所有的节点所共享。
//ThousandEwindows xp ression类:用来核对罗马字符中的 M ;
//HundredEwindows xp ression类:用来核对罗马字符中的C, CD, D or CM;
//TenEwindows xp ression类:用来核对罗马字附中的X, XL, L and XC;
//OneEwindows xp ression类:用来核对罗马字附中的I, II, III, IV, V, VI, VI, VII, VIII, IX。
namespace ConsoleApplication13
{
class Context
{
private string _input;
private int _output;
public Context(string input)
{
this._input = input;
}
public string Input
{
get { return _input; }
set { _input = value; }
}
public int Output
{
get { return _output; }
set { _output = value; }
}
}
abstract class Ewindowsxpression
{
public void Interpret(Context context)
{
if (context.Input.Length == 0)
return;
if (context.Input.StartsWith(Nine()))
{
context.Output += (9 * Multiplier());
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Four()))
{
context.Output += (4 * Multiplier());
context.Input = context.Input.Substring(2);
}
else if (context.Input.StartsWith(Five()))
{
context.Output += (5 * Multiplier());
context.Input = context.Input.Substring(1);
}
while (context.Input.StartsWith(One()))
{
context.Output += (1 * Multiplier());
context.Input = context.Input.Substring(1);
}
}
public abstract string One();
public abstract string Four();
public abstract string Five();
public abstract string Nine();
public abstract int Multiplier();
}
/// <summary>
/// A 'TerminalEwindows xp ression' class
/// <remarks>
/// 用来核对罗马字符中的 M
/// </remarks>
/// </summary>
class ThousandEwindowsxpression : Ewindowsxpression
{
public override string One() { return "M"; }
public override string Four() { return " "; }
public override string Five() { return " "; }
public override string Nine() { return " "; }
public override int Multiplier() { return 1000; }
}
/// <summary>
/// A 'TerminalEwindowsxpression' class
/// <remarks>
/// 用来核对罗马字符中的C, CD, D or CM;
/// </remarks>
/// </summary>
class HundredEwindowsxpression : Ewindowsxpression
{
public override string One() { return "C"; }
public override string Four() { return "CD"; }
public override string Five() { return "D"; }
public override string Nine() { return "CM"; }
public override int Multiplier() { return 100; }
}
/// <summary>
/// A 'TerminalEwindows xp ression' class
/// <remarks>
/// 用来核对罗马字附中的X, XL, L and XC
/// </remarks>
/// </summary>
class TenEwindowsxpression : Ewindowsxpression
{
public override string One() { return "X"; }
public override string Four() { return "XL"; }
public override string Five() { return "L"; }
public override string Nine() { return "XC"; }
public override int Multiplier() { return 10; }
}
/// <summary>
/// A 'TerminalEwindows xp ression' class
/// <remarks>
/// 用来核对罗马字附中的I, II, III, IV, V, VI, VI, VII, VIII, IX
/// </remarks>
/// </summary>
class OneEwindowsxpression : Ewindowsxpression
{
public override string One() { return "I"; }
public override string Four() { return "IV"; }
public override string Five() { return "V"; }
public override string Nine() { return "IX"; }
public override int Multiplier() { return 1; }
}
class Program
{
static void Main(string[] args)
{
string roman = "MCMXXVIII";//(1*1000 + 9*100 + 1*10 + 1*10 + 8 = 1928)
Context context = new Context(roman);
// Build the 'parse tree'
List<Ewindowsxpression> tree = new List<Ewindowsxpression>();
tree.Add(new ThousandEwindowsxpression());
tree.Add(new HundredEwindowsxpression());
tree.Add(new TenEwindowsxpression());
tree.Add(new OneEwindowsxpression());
// Interpret
foreach (Ewindowsxpression ewindowsxp in tree)
{
ewindowsxp.Interpret(context);
}
Console.WriteLine("{0} = {1}", roman, context.Output);
Console.ReadKey();
}
}
}
二十七:访问者模式:示意一个作用于某对象结构中的元素操作。它使你能够在不改动各元素类的前提下定义作用于这些元素的新操作,它把数据结构和作用于结构上的操作之间的耦合性解脱开,使的操作结合能够相对自由地演化。优点是添加新的操作很基本 ,因为添加一个新的操作就意味着添加一个新的访问者,访问者模式将相关的行为集中到一个访问对象中。
访问者模式的目标是要把处理从数据结构分离出来。假如系统有比较稳定的数据结构,又有易于改动的算法的话,运用访问者模式是个不错的挑选,因为访问者模式使的算法操作的添加变的基本 。相反,假如系统的数据结构不稳定,易于改动,则此系统就不适合运用访问者模式了。
abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(ConcreteElementB concreteElementB);
}
class ConcreteVisitor1 : 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);
}
}
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 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 (Element e in elements)
{
e.Accept(visitor);
}
}
}
class Program
{
static void Main(string[] args)
{
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
o.Accept(v1);
o.Accept(v2);
Console.Read();
}
}