大话设计模式

大话设计模式
一.简单工厂模式

创建一个工厂对象,根据不同的需求创建不同的对象,这些对象又继承了同一个父类,父类里有一个抽象方法,这些子类重写了父类的这个方法。示例见P21、P27

商场收银系统
//现金收费抽象类
abstract class CashSuper
{
    public abstract double acceptCash(double money);
}

//正常收费子类
Class CashNormal : CashSuper
{
    public override double acceptCash(double money)
    {
      return money;
    }
}

//打折收费子类
Class CashRebate : CashSuper
{
    private double moneyRebate = 1d;//折扣,如八折:0.8
    publc CashRebate(string moneyRebate)
    {
       this.moneyRebate=double.Parse(moneyRebate)
    }
    
    public override double acceptCash(double money)
    {
      return money * moneyRebate;
    }
}

//返利收费子类
Class CashReturn : CashSuper
{
    private double moneyCondition = 0.0d;
    private double moneyReturn = 0.0d;
    publc CashReturn(string moneyCondition, string moneyReturn)
    {
       this.moneyConditon=double.Parse(moneyCondition)
       this.moneyReturn=double.Parse(moneyReturn)
    }
    
    public override double acceptCash(double money)
    {
      double result = money;
      if(money >= moneyCondition)
        result = money -Math.Floor(money/moneyCondition) * moneyReturn;
        
      return result;
    }
}


//现金收费工厂类
class CashFactory
{
    public static CashSuper createCashAccept(string type)
    {
        CashSuper cs = null;
        switch(type)
        {
                cast "正常收费":
                  cs = new CashNormal();
                  break;
                 cast "满300减100":
                  CashReturn cr1 = new CashReturn("300","100");
                  cs = cr1;
                  break;
                 cast "打八折":
                  CashRebate cr2 = new CashRebate("0.8");
                  cs = cr2;
                  break;
        }
    }
}
 

//客户端窗体程序
double total =0.0d;
private void btnOk_click(object sender,EventArgs e)
{
    //工厂方法接收不同的折扣
    CashSuper csuper= CashFactory.cerateCashAccept(cbxType.SelectedItem.ToString());
    double totalPrices= 0d;
    //计算总钱数
    totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text))*Convert.ToDouble(txtNum.Text));
    total = total +totalPrices;
}
二.策略模式

简单工厂模式中不同的需求会有不同的算法(策略),将不同的算法抽象出一个抽象策略,具体的策略继承抽象策略,构建一个Context(上下文)类,其中的方法调用抽象策略的方法,构造参数为抽象策略,具体代码见P26

//构建Context
class CashContext
{
    private CashSuper cs;
    public CashContext(CashSuper csuper)
    {
        this.cs = csuper;
    }
    
    public double GetResult(double money)
    {
        return cs.acceptCash(money)
    }
}

//客户端窗体程序
double total =0.0d;
private void btnOk_click(object sender,EventArgs e)
{
    CashContext cc = null;
    //工厂方法接收不同的折扣
    switch (cbxType.SelectedItem.ToString())
    {
             cast "正常收费":
                  cc = new CashContext(new CashNormal());
                  break;
             cast "满300减100":
                  cc = new CashContext(new CashReturn("300","100"));
                  break;
             cast "打八折":
                  cc = new CashContext(new CashRebate("0.8"));
                  break;
    }
    double totalPrices= 0d;
    //计算总钱数
    totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text))*Convert.ToDouble(txtNum.Text));
    total = total +totalPrices;
}
三.策略与简单工厂结合

和简单工厂类似,根据不同的需求创建不同的对象,不同的是,将创建完的对象赋给上下文拥有的父类,

再通过内部的方法调取父类的方法(这时已经是子类的方法)

//改造Context
class CashContext
{
    CashSuper cs = null;
    public CashContext(string type)
    {
         switch (type)
      {
             cast "正常收费":
                  CashNormal cs0 = new CashNormal();
                  cs =cs0
                  break;
                 cast "满300减100":
                  CashReturn cr1 = new CashReturn("300","100");
                  cs = cr1;
                  break;
                 cast "打八折":
                  CashRebate cr2 = new CashRebate("0.8");
                  cs = cr2;
                  break;
      }
    }
    
    public double GetResult(double money)
    {
        return cs.acceptCash(money)
    }
}


//客户端窗体程序
double total =0.0d;
private void btnOk_click(object sender,EventArgs e)
{
    CashContext cc = new CashContext(cbxType.SelectedItem.ToString());
   
    double totalPrices= 0d;
    //计算总钱数
    totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text))*Convert.ToDouble(txtNum.Text));
    total = total +totalPrices;
}
四.开发-封闭原则

对于扩展是开放的,对于更改是封闭的

五.装饰模式

装饰模式就是构造一个装饰类,构造参数为将要进行装饰的对象,装饰类中的方法为装饰对象的方法,

然后具体的装饰的对象再继承装饰类,其中执行的方法可以进行制造装饰的顺序

class Person
{
    public Person()
    {}
    private string name;
    public Person(string name)
    {
        this.name=name;
    }
    public virtual void Show()
    {
        Console.WriteLine("装扮的{0}",name);
    }
}

服饰类
class Finery:Person
{
   protected Person component;
   public void Decorate(Person component)
   {
       this.component = component;
   }
   
   public override void Show()
   {
     if(component!=null)
     {
        component.Show();
     }
   }
}

具体服饰类
class Tshirt:Finery
{
  public override void Show()
  {
      Console.Write("大T恤")
      base.Show();
  }
}


class BigTrouser:Finery
{
  public override void Show()
  {
      Console.Write("垮裤");
      base.Show();
  }
}
//其余类似,省略

static void Main(string[] args)
{
    Person xc = new Person("小菜");
    Console.WriteLine("\n第一种装扮");
        
        Sneaker pqx = new  Sneakwers();
        BigTrouser kk = new BigTrouser();
        TShirts dtx = new TShirts();
    
    pqx.Decorate(xc);
    kk.Decorate(pqx);
    dtx.Decorate(kk);
    dtx.Show();
}

六.代理模式

Subject类,定义了RealSubject和Proxy的共用接口,这样就在任何时候使用RealSubject的地方都可以使用Proxy。
abstract class Subject
{
public abstract void Request();
}

RealSubject类,定义Proxy 所代表的真实实体
class RealSubject : Subject
{
public override void Request()
{
      Console.WriteLine("真实的请求")}
}

Proxy类,保存一个引用使得代理可以访问实体,并提供一个与Subject 的接口相同的接口,这样代理就可以用来代替实体。
class Proxy :Subject
{
    RealSubject realSubject;
    public overlide ovid Request()
    {
        if(realSubject ==null)
        {
            realSubject=new RealSubject();
        }
        realSubject.Request();
    }
}

客户端代码

static void Main(string[] args)
{
    Proxy proxy = new Proxy();
    proxy.Request();
    Console.Read();
}
七.工厂方法模式

工厂方法对简单工厂又进行了进一步拆分,不同的工厂类实现同一个工厂接口,重写工厂接口的方法,创建不同的代理对象(大学生和社区志愿者都是雷锋的代理,都继承了雷锋)

//雷锋工厂
interface IFactory
{
    LeiFeng CreateLeiFeng();
}
//学雷锋的大学生工厂
class UndergraduateFactory :IFactory
{
    public LeiFeng CreateLeiFeng()
    {
        return new Undergraduate();
    }
}

//社区志愿者工厂
class VolunteerFactory :IFactory
{
    public LeiFeng CreateLeiFeng()
    {
        return new Volunteer();
    }
}


//客户端调用
//工厂方法模式
IFactory factory = new UndergraduateFactory();
LeiFeng student = factory.CreateLeiFeng();

student.BuyRice();
student.Sweep();
student.Wash();
八.原型模式

创建当前对象的浅表副本。方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其副本引用同一对象。

浅复制:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。

//工作经历类
class WorkExperience
{
    private string WorkDate;
    public string WorkDate;
    {
        get {return WorkDate;}
        set {workDate = value}
    }
    private string company;
    public string Company
    {
        get{return company;}
        set{company = value;}
    }
}

//简历类
class Resume : ICloneable
{
  private string name;
  private string age;
  private string sex;
  private WorkExperience work;
  
  public Resume(string name)
  {
     this.name=name;
     work=new WorkExperience();
  }
  
  //设置个人信息
  public void SetPersonalInfo(string sex,string age)
  {
     this.sex = sex;
     this.age = age;
  }
  
  
  //设置工作经历
  public void SetWorkExperience(string workDate,string company)
  {
     work.WorkDate = workDate;
     work.Company = company;
  }
  
  //显示
  public void Display()
  {
    Console.WriteLine("{0} {1} {2}",name,sex,age);
    Console.WriteLine("工作经历:{0} {1}",work.WorkDate,work.Company);
  }
  
  
  public Object Clone()
  {
    return (Object)this.MemberwiseClone();
  }
}

//客户端代码
static void Main (string[] args)
{
    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");
    c.SetWorkExperience("1998-2003","zz公司");
        
     a.Display();
     b.Display();
     c.Display();
    
    Console.read();

}

//结果
大鸟 男 29
工作经历 1998-2003 ZZ企业
大鸟 男 29
工作经历 1998-2003 ZZ企业
大鸟 男 24
工作经历 1998-2003 ZZ企业

深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。

//工作经历类
class WorkExperience : ICloneable
{
    private string WorkDate;
    public string WorkDate;
    {
        get {return WorkDate;}
        set {workDate = value}
    }
    private string company;
    public string Company
    {
        get{return company;}
        set{company = value;}
    }
    
     public Object Clone()
  {
    return (Object)this.MemberwiseClone();
  }
}


//简历类
class Resume : ICloneable
{
  private string name;
  private string age;
  private string sex;
  private WorkExperience work;
  
  public Resume(string name)
  {
     this.name=name;
     work=new WorkExperience();
  }
  
  private Resume(WorkExperience work)
  {
     this.work = (WorkExperience)work.Clone();
  }
  
  //设置个人信息
  public void SetPersonalInfo(string sex,string age)
  {
     this.sex = sex;
     this.age = age;
  }
  
  
  //设置工作经历
  public void SetWorkExperience(string workDate,string company)
  {
     work.WorkDate = workDate;
     work.Company = company;
  }
  
  //显示
  public void Display()
  {
    Console.WriteLine("{0} {1} {2}",name,sex,age);
    Console.WriteLine("工作经历:{0} {1}",work.WorkDate,work.Company);
  }
  
  
  public Object Clone()
  {
   Resume a = new Resume(this.work);
   obj.name=this.name;
   obj.sex=this.sex;
   obj.age=this.age;
    return obj;
  }
}

//客户端代码
static void Main (string[] args)
{
    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");
    c.SetWorkExperience("1998-2003","zz公司");
        
     a.Display();
     b.Display();
     c.Display();
    
    Console.read();

}

//结果
大鸟 男 29
工作经历 1998-2000 XX企业
大鸟 男 29
工作经历 1998-2006 YY企业
大鸟 男 24
工作经历 1998-2003 ZZ企业
九.模板方法模式

将相同的代码都抽取出来,当具体的实现细节不同时要抽取一个方法,具体示例见P95

十.迪米特法则

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

此法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。

十一.依赖倒转原则

A.高层模块不应该依赖底层模块。两个都应该依赖抽象。

B.抽象不应该依赖细节。细节应该依赖抽象。

十二.里氏代换原则

子类型必须能够代替掉它们的父类型

子类型拥有父类型所有的非private的行为和属性

十三.外观模式

为子系统的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

//四个子系统的类
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("方法组A")
        one.MethodOne();
        two.MethodTwo();
        four.MethodFour();
    }
    public void MethodB()
    {
        Console.WriteLine("方法组B")
       
        two.MethodTwo();
        three.MethodThree();
        Console.Read();
    }
}


//客户端调用   由于facade的作用,客户端可以根本不知道三个子系统的存在
static void Main(string[] args)
{
    Facade facade = new Facade();
    facade.MethodA();
    facade.MethodB();
    
    Console.Read();
}

何时使用外观模式?

1.在设计初级阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。

2.在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观facade可以提供一个简单的接口,减少它们之间的依赖。

3.在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为新系统开发一个外观facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统和Facade对象交互,Facade与遗留代码交互所有复杂的工作。

十四.建造者模式

主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。

Project类——产品类,由多个部件组成

class Product
{
    List<string> parts = new List<string>();
    public void Add(string part){
        parts.Add(part);
    }
    
    public void Show(){
        Console.WriteLine("产品创建")
        foreach(string part in parts)
        {
            Console.WriteLine(part);
        }
    }
}

//Builder类——抽象构造者,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult。
abstract class Builder
{
    public abstract void BuildPartA();
    public abstract void BuildPartB();
    public abstract Product GetResult();
}

ConcreteBuilder1类——具体建造类
class ConcreteBuilder1:Builder
{
	private Product product = new Product();
    public override void BuilderPartA(){
        product.Add("部件A");
    }
     public override void BuilderPartB(){
        product.Add("部件B");
    }
    
    public override Product GetResult()
    {
        return product;
    }
}

ConcreteBuilder2类——具体建造类
class ConcreteBuilder1:Builder
{
	private Product product = new Product();
    public override void BuilderPartA(){
        product.Add("部件X");
    }
     public override void BuilderPartB(){
        product.Add("部件Y");
    }
    
    public override Product GetResult()
    {
        return product;
    }
}

Director类——指挥者类
class Director
{
    public void Construct(Builder builder)
    {
        builder.BuilderPartA();
        builder.BuilderPartB();
    }
}
//客户端代码,客户不需知道具体的建造过程
static void Main(string[] args)
{
    Director director = new Director();
    Builder b1 = new ConcreteBuilder1();
    Builder b2 = new ConcreteBulider2();
    
    director.Construct(b1);
    Product p1 = b1.getResult();
    p1.show();
    
    director.Construct(b2);
    Product p2 = b2.getResult();
    p2.show();
    
    Console.Read();
 
}
十五.观察者模式

观察者模式又叫发布-订阅模式

其定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使它们能够自动更新自己。

其所做的工作就是在解除耦合。让耦合的双方都依赖于抽象而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。

抽象通知者接口

//通知者接口
interface Subject
{
    void Attach(Observer observer);
    void Detach(Observer observer);
    void Notify();
    string SubjectState
    {
        get;
        set;
    }
}

具体的通知者类可能是前台,也可能是老板,它们也许有各自的一些方法,但对于通知者来说,它们是一样的,所以它们都去实现这个接口。

class Boss:Subject
{
	//同事列表
	private List<Observer> observers = new List<Observer>();
	private string action;
	
	//增加
	public void Attach(Observer observer)
    {
    	obsrever.Add(observer);
    }
    //减少
	public void Detach(Observer observer)
    {
    	obsrever.Remove(observer);
    }
    //通知
    public void Notify()
    {
    	foreach(Observer o in observer)
    	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);
    }
}

//客户端代码如下:
//老板胡汉三
Boss huansan = new Boss();

//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹",huhansan);
//看NBA的同事
NBAbserver tongshi2 = new NBAObserver("易官查",huhansan);

huhuansan.Attach(tongshi1);
huhuansan.Attach(tongshi2);
//魏关姹 其实没有被老板通知到,所以减去
huhuansan.Detach(tongshi1);

//老板回来
huhansan.SubjectState = "我胡汉三回来了"//发出通知
huhansan.Notify();
//运行结果
我胡汉三回来了,易官查 关闭NBA直播,继续工作!

缺点:

尽管已经用了依赖倒转原则,但是‘抽象通知者还是依赖于‘抽象观察者’,这时事件委托实现就应运而生了。

十六.事件委托实现

'‘看股票观察者’'类和看“NBA观察者”类,去掉了父类“抽象观察类”,所以补上一些代码,并将“更新”方法名改为各自适合的方法名。

//看股票的同事
class StockObserver
{
	private string name;
    protected Subject sub;
    
    public StockObserver(string name,Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }
    

    public override void CloseStockMarket()
    {
        Console.WriteLine("{0} {1} 关闭股票行情,继续工作!",sub.SubjectState,name);
    }
}

//看NBA的同事
class NBAObserver 
{
	private string name;
    protected Subject sub;
    
    public NBAObserver(string name,Subject sub)
    {
        this.name = name;
        this.sub = sub;
    }
    

    public override void CloseNBADirectSeeding()
    {
        Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!",sub.SubjectState,name);
    }
}

//通知者接口
interface Subject 
{
    void Notify();
    string SubjectState
    {
        get;
        set;
    }
}

//声明一个委托,名称叫“EventHandler(事件处理程序)”,无参数,无返回值。
delegate void EventHandler();

//老板类和前台秘书类
class Boss:Subject
{
	//声明一事件update,类型为委托EventHandler
	//声明一“EventHandler(事件处理程序)”的委托事件,名称交“Update(更新)”
	public event EventHandler Update;
	private string action;
	
	
    //通知
    public void Notify()
    {
    	Update();
    }
    
    //老板状态
    public string SubjectState
    {
    	get{return action;}
    	set{action = value;}
    }
}

class Secretary:Subject
{
	//与老板类类似,省略
}

//客户端代码
//老板胡汉三
Boss huhansan = new Boss();
//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹",huhansan);

//看NBA的同事
NBAObserver tongshi2 = new NBAObserver("易管查",huhansan);



//将“看股票者”的关闭股票程序方法和看“NBA者”的关闭NBA直播的方法挂钩到老板的更新上,也就是将两不同类的不同方法委托给老板类的更新了。
huhansan.Update += new EventHandler(tongshi1.CloseStockMarket);
huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);

//显示结果
我胡汉三回来了,魏关姹 关闭股票行情,继续工作!
我胡汉三回来了,易管查 关闭NBA直播,继续工作!

委托就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的“类”,委托的实例将代表一个具体的函数。

一个委托可以搭载多个方法,所有的方法被依次唤起。更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。

但委托也是有前提的,那就是委托对象所搭载的方法必须具有相同的原形和形式,也就是拥有相同的参数列表和返回值类型。


十七.抽象工厂模式
interface Department
{
    void Insert(Department department);
    Department GetDepartment(int id);
}

//SqlserverDepartment类,用于访问SQLServer的Department。
class SqlserverDepartment:Department
{
	public void Insert(Department department)
    {
    	Console.WriteLine("在SQLServer中给Department表增加一条记录")}
    
    public Department GetDepartment(int id)
    {
    	Console.WriteLine("在SQLServer中根据id得到Department表的一条记录")}
}
//AccessDepartment类,用于访问Access的Department。
class AccessDepartment:Department
{
	public void Insert(Department department)
    {
    	Console.WriteLine("在Access中给Department表增加一条记录")}
    
    public Department GetDepartment(int id)
    {
    	Console.WriteLine("在Access中根据id得到Department表的一条记录")}
}

//Ifactory 接口 定义一个创建访问Department表对象的抽象的工厂接口

interface Factory
{
    User CreateUser();
    Department CreateDepartment();
}

//SqlServerFactory类,实现Factory 接口,实例化SqlserverUser 和SqlserverDepartment
class SqlServerFactory : Factory
{
	public User CreateUser()
    {
    	return new SqlserverUser();
    }
    
    public Department CreateDepartment()
    {
    	return new SqlserverDepartment();
    }
}

//AccessFactory类,实现Factory 接口,实例化AccessUser 和AccessDepartment
class AccessFactory : Factory
{
	public User CreateUser()
    {
    	return new AccessUser();
    }
    
    public Department CreateDepartment()
    {
    	return new AccessDepartment();
    }
}

//客户端代码
static void Main(string[] args)
{
    User user = new User();
    Department dept = new  Department();
    
    //Factory factory = new SqlServerfactory();
    Factory factory = new  AccessFactory();
    
    User iu = factory.CreateUser();
    iu.Insert(user);
    iu.GetUser(1);
    
    Departmnet id = factory.CreateDepartment();
    id.Insert(dept);
    id.GetDepartment(1);
    
    Console.Read();
}

//结果显示如下
在Access中给User表添加一条记录
在Access中根据id得到user表的一条记录
在Access中给Department表添加一条记录
在Access中根据id得到Department表的一条记录

优点:

1.易于交换产品系列,由于具体工厂类,例如Factory factory = new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,他需要改变具体工厂即可使用不同的产品配置。我们的设计不能去防止需求的更改,那么我们的目的是让改动变得最小。

2.它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中。

缺点:

1.如果现在要增加项目表Project ,需要改动很多类

2.在客户端很多地方都用到User和Department,而每次使用这个类都需要先声明Factory factory = new SqlserverFactory();如果有100次调用,就会有100次改动Factory factory = new AccessFactory();

简单工厂来改进抽象工厂

class DataAccess
{
    private static readonly string db = "Sqlserver";
    //private static readonly string db = "Access";
    
    public static User CreateUser()
    {
        User result = null;
        switch(db)
        {
            case "Sqlserver":
                result = new SqlServerUser();
                break;
            case "Access":
                result = new AccessUser();
                break;   
        }
        return result;
    }
    
     public static Department CreateDepartment()
    {
        Department result = null;
        switch(db)
        {
            case "Sqlserver":
                result = new SqlServerDepartment();
                break;
            case "Access":
                result = new AccessDepartment();
                break;   
        }
        return result;
    }
}

//客户端代码
static void Main(string[] args)
{
    User user = new User();
    Department dept = new  Department();
    
    //直接得到实际的数据库访问实例,而不存在任何的依赖
    User iu = DataAccess.CreateUser();
    iu.Insert(user);
    iu.GetUser(1);
    
    Departmnet id = DataAccess.CreateDepartment();
    id.Insert(dept);
    id.GetDepartment(1);
    
    Console.Read();
}

如果需要增加Oracle数据库访问,原来抽象工厂只增加一个OracleFactory工厂类就可以了,现在需要在DataAccess类中每个方法的switch中加case了。

用反射+抽象工厂的数据访问程序

反射格式

Assembly.Load(“程序集名称”).CreateInstance(“命名空间.类名称”)

//常规写法
User result = new  SqlserverUser();
//反射的写法
using System.Reflection;

User result = (User)Assembly.Load("抽象工厂模式").CreateInstance("抽象工厂模式.SqlserverUser");


class DataAccess
{
    private static readonly string AssemblyName = "抽象工厂模式";
    private static readonly string db = "Sqlserver";
    
    public static User CreateUser()
    {
       string className = AssemblyName+"."+db+"User";
       return (User)Assembly.Load(AssemblyName).CreateInstance(className);
    }
    
     public static Department CreateDepartment()
    {
       string className = AssemblyName+"."+db+"User";
       return (User)Assembly.Load(AssemblyName).CreateInstance(className);
    }
}

//如果增加Oracle数据库
更改 private static readonly string db = "Sqlserver";private static readonly string db = "Oracle";
//db采用在配置文件中配置即可


十八.状态模式

如果条件分支过多时,将条件分支拆分出来,用一个类代替

抽象状态类,定义一个抽象方法“写程序”

//抽象状态
public abstract class State
{
    public abstract void WriteProgram(Work w);
}

//上午工作状态
public class ForenoonState : State
{
	public override void WriteProgram (Work w)
    {
    if(w.Hour<12){
     	Console.WriteLine("当前时间:{0}点 上午工作,精神百倍",w.Hour);
    }
    else
    {
        w.SetState(new NoonState());
        w.WriteProgram();
    }
    }
}


//中午工作状态
public class NoonState : State
{
	public override void WriteProgram (Work w)
    {
    if(w.Hour<13){
     	Console.WriteLine("当前时间:{0}点 饿了,午饭;犯困,午休",w.Hour);
    }
    else
    {
        w.SetState(new AfternoonState());
        w.WriteProgram();
    }
    }
}


//下午工作状态
public class AfternoonState : State
{
	public override void WriteProgram (Work w)
    {
    if(w.Hour<17){
     	Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力",w.Hour);
    }
    else
    {
        w.SetState(new EveningState());
        w.WriteProgram();
    }
    }
}


//晚间工作状态
public class EveningState : State
{
	public override void WriteProgram (Work w)
    {
    if(w.TaskFinished){
     	w.SetState(new RestState());
        w.WriteProgram();
    }
    else
    {
       if(w.Hour<21)
       {
       		Console.WriteLine("当前时间:{0}点 加班哦,疲累之极",w.Hour);
       }
       else
       {
       		 w.SetState(new SleepingState());
        	 w.WriteProgram();
       }
    }
    }
}

//睡眠状态
public class SleepingState : State
{
	public override void WriteProgram (Work w)
    {
    if(w.Hour<17){
     	Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力",w.Hour);
    }
    else
    {
        w.SetState(new EveningState());
        w.WriteProgram();
    }
    }
}

//下班休息状态
public class RestState : State
{
	public override void WriteProgram (Work w)
    {
     	Console.WriteLine("当前时间:{0}点 下班回家了",w.Hour);
    }
}

//工作
public class Work
{
    private State current;
    public Work()
    {
        current = new ForenoonState();
    }
    
    private double hour;
    public double Hour;
    {
        get{return hour;}
        set{hour = value}
    }
    
    private bool finish = false;
    public bool TaskFinished
    {
        get{return finish;}
        set{finish = value;}
    }
    
    public void SetState(State s)
    {
        current =s;
    }
    
    public void WriteProgram()
    {
        current.WriteProgram(this);
    }
}


static void Main(string[] args)
{
    //紧急项目
    Work emergencyProjects = new  Work();
    emergencyProjects.Hour = 9;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 10;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 12;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 13;
    emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 14;
    emergencyProjects.WriteProgram();
     emergencyProjects.Hour = 17;
    
    emergencyProjects.TaskFinished=false;
    
     emergencyProjects.WriteProgram();
    emergencyProjects.Hour = 19;
    emergencyProjects.WriteProgram();
     emergencyProjects.Hour = 22;
     emergencyProjects.WriteProgram();
    
    Console.Read();
    
}
//结果表现如下
当前时间:9点 上午工作,精神百倍
当前时间:10点 上午工作,精神百倍
当前时间:12点 饿了,午饭;犯困,午休
当前时间:13点 下午状态还不错,继续努力
当前时间:14点 下午状态还不错,继续努力
当前时间:17点 加班哦,疲累之极
当前时间:19点 加班哦,疲累之极
当前时间:22点 不行了,睡着了

十九.适配器模式

//客户所期待的接口
class Target
{
    public virtual void Request()
    {
        Console.WriteLine("普通请求!")}
}
//需要适配的类
class Adaptee
{
    public void SpecificRequest()
    {
        Console.WriteLine("特殊请求!")
    }
}
//适配(通过在内部包装一个Adaptee对象,把源接口转换成目标接口)
class Adapter : Target
{
	private Adaptee adaptee = new Adaptee();
	
	public override void Request()
    {
    	adaptee.SpecificRequest();
    }
}

//客户端
static void Main(string[] args)
{
    Target target = new Adapter();
    target.Request();
    
    Console.Read();
}

二十.备忘录模式

class GameRole
{
    //生命力
    private int vit;
    public int Vitality;
    //攻击力
    private int atk;
    public int Attack;
    //防御力
    private int def;
    public int Defense;
    
    //保存角色状态
    public RoleStateMemnto SaveState()
    {
        return (new RoleStateMemento(vit,atk,def))
    }
    
    //恢复角色状态
    public void RecoveryState(RoleStateMemento memento)
    {
        this.vit= memento.Vitality;
        this.atk=memento.Attack;
        this.def= memento.Defense;
    }
}

//角色状态存储箱
class RoleStateMemento
{
    private int vit;
    private int atk;
    private int def;
    public RoleStateMemento(int vit,int atk,int def)
    {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }
    
    
    //生命力
    public int Vitality
    {
        get{return vit;}
        set{vit = value;}
    }
    
    //攻击力
    public int Attack
    {
        get{return atk;}
        set{ack = value;}
    }
    
    //防御力
    public int Defense
    {
        get{return def;}
        set{def = value;}
    }
    
    //角色状态管理类
    class RoleStateCaretaker
    {
        private RoleStateMemento memento;
    
        public RoleStateMemento Memento
        {
            get{return memento;}
            set{memento value;}
        }
    
    }
    
    //客户端代码
    static void Main(string[] args)
    {
        //大战Boss前
        GameRole lixiaoyao = new GameRole();
        lixiaoyao.GetInitState();
        lixiaoyao.StateDisplay();
        
        //保存进度
        RoleStateCaretaker stateAdmin = new RoleStateCaretaker();
        stateAdmin.Memento = lixiaoyao.SaveState();
        
        //大战Boss时,损耗严重
        lixiaoyao.Fight();
        lixiaoyao.StateDisplay();
        
        //恢复之前状态
        lixiaoyao.RecoveryState(stateAdmin.Memento);
        lixiaoyao.StateDisplay();
        
        Console.Read();
    }
    
}
二十一.组合模式

将对象组合成树形结构以表示部分-整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

用于菜单的分级,树状结构

//Component 为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件。
abstract class Component
{
    protected string name;
    public Component(string name)
    {
        this.name = name;
    }
    //通常都用Add和remove方法来提供增加或移除树叶或树枝的功能
    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
}

//Leaf 在组合中表示叶节点对象,叶节点没有子节点。
class Leaf : Component
{
	public Leaf(string name):base(name){}


//由于叶子节点没有再增加分枝和树叶,所有Add 和Remove 方法实现它没有意义,但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具备完全一致的接口
	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);    
    }
}


//Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add 和删除Remove
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);//递归
        }
    }
}

//客户端代码,能通过Component 接口操作组合部件的对象
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");
    comp.Add(new Leaf("Leaf XXA"));
    comp.Add(new Leaf("Leaf XXB"));
    
    root.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();
}


//结果
-root
---Leaf A
---Leaf B
---Composite X
-----Leaf XA
-----Leaf XB
-----Composite XY
-------Leaf XYA
-------Leaf XYB
---Leaf C
二十二.迭代器模式
二十三.单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

二十四.桥接模式

实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少他们之间的耦合。

二十五.命令模式

用来声明执行操作的接口

abstract class Command
{
    protected Receiver reveiver;
    public Command(Receiver receiver)
    {
        this.receiver = receiver;
    }
    
    abstract public void Execute();
}

//将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute。

class ConcreteCommand : Command
{
	public ConcreteCommand(Receiver receiver) : base(receiver)
	{ }
	
	public override void Execute()
    {
    	receiver.Action();
    }
}

//invoker类,要求该命令执行这个请求。

class Invoker
{
    private Command command;
    
    public void SetCommand(Command command)
    {
        this.command = command;
    }
    
    public void ExecuteCommand()
    {
        command.Execute();
    }
}

//Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接口者。
class Receiver
{
    public void Action()
    {
        Console.WriteLine("执行请求!")}
}

//客户端代码,创建一个具体命令对象并设定它的接收者

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 Manager
{
    protect string name;
    //管理者的上级
    protect Manager superior;
    
    public Manager(string name)
    {
        this.name = name;
    }
    
    //设置管理者的上级
    public void SetSuperior(Manager superior)
    {
        this.superior = superior;
    }
    
    //申请请求
    abstract public void RequestApplication(Request request);
}

//经理
class CommonManager : Manager
{
	public CommonManager(string name) : base(name){ }
	
	public override void RequestApplication(Request request)
    {
    	if(Request.RequestType == "请假" && request.Number <= 2)
        {
        	Console.WriteLine("{0}:{1} 数量{2} 被批准",name,request.RequestContent,request.Number);
        	
        }
        else
        {
        	if(superior != null)
        		superior.RequestApplications(request);
        }
    }
}

//总监
class Majordomo : Manager
{
	public Majordomo(string name) : base(name){ }
	
	public override void RequestApplication(Request request)
    {
    	if(Request.RequestType == "请假" && request.Number <= 5)
        {
        	Console.WriteLine("{0}:{1} 数量{2} 被批准",name,request.RequestContent,request.Number);
        	
        }
        else
        {
        	if(superior != null)
        		superior.RequestApplications(request);
        }
    }
}

//总经理
class GeneralManager : Manager
{
	public GeneralManager(string name) : base(name){ }
	
	public override void RequestApplication(Request request)
    {
    	if(Request.RequestType == "请假")
        {
        	Console.WriteLine("{0}:{1} 数量{2} 被批准",name,request.RequestContent,request.Number);
        	
        }
        else if(Request.RequestType == "加薪" && request.Number <= 500)
        {
        	Console.WriteLine("{0}:{1} 数量{2} 被批准",name,request.RequestContent,request.Number);
        }
        else if(Request.RequestType == "加薪" && request.Number > 500)
        {
        	Console.WriteLine("{0}:{1} 数量{2} 再说吧",name,request.RequestContent,request.Number);
        }
    }
}



//客户端代码
static void Main(string[] args)
{
    CommonManager jinli = new CommonManager("金利");
    Majordomo zongjian = new Majordomo("宗剑");
    GeneralManager zhongjianli = new GenerialManager("钟精励");
    jinli.SetSuperior(zongjian);
    zongjian.SetSuperior(zhongjingli);
    
    Request request = new Request();
    request.RequestType = "请假";
    request.RequestContent = "小菜请假";
    request.Number = 1;
    jingli.RequestApplication(request);
    
    Request request2 = new Request();
    request.RequestType = "请假";
    request.RequestContent = "小菜请假";
    request.Number = 4;
    jingli.RequestApplication(request2);
    
    Request request3 = new Request();
    request.RequestType = "加薪";
    request.RequestContent = "小菜请求加薪";
    request.Number = 500;
    jingli.RequestApplication(request3);
    
    Request request4 = new Request();
    request.RequestType = "加薪";
    request.RequestContent = "小菜请求加薪";
    request.Number = 1000;
    jingli.RequestApplication(request4);
    
    Console.Read();
}

//结果
金利:小菜请假 数量1 被批准
宗剑:小菜请假 数量4 被批准
钟精励:小菜请求加薪 数量500 被批准
钟精励:小菜请求加薪 数量1000 再说吧
二十八.中介者模式

优点:Mediator 的出现减少了各个Colleague 的耦合,使得可以独立的改变和复用各个Colleague类和Mediator

缺点:是得Mediator变得非常复杂

二十九.享元模式

优点:可以运用共享技术有效的支持大量细粒度的对象

缺点:使得程序的逻辑复杂化,应当在有足够多的对象实例可供共享时才值得使用共享模式

三十.解释器模式

//演奏内容
class PlayContext
{
    //演奏文本
    private string text;
    public string PlayText;
    {
        get{return text;}
        set{text = value;}
    }
}
//表达式类
abstract class Expression
{
    //解释器
    public void Interpret(PlayContext context)
    {
        if(context.PlayText.Length==0)
        {
            return;
        }
        else
        {
            string playKey = context.PlayText.Substring(0,1);
            context.PlayText = context.PlayText.Substring(2);
            double playValue = Convert.ToDouble(context.PlayText.Substring(0,context.PlayText.IndexOf(" ")));
            context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ") +1);
            Excute(playKey,playValue);
        }
         
    }
    
    //执行
    public abstract void Excute(string key,double vlaue);
}

//音符类
class Note : Expression
{
 	public override void Excute(string key,double value)
    {
    	string note = "";
    	switch(key)
        {
        	case "C":
				note = "1";
				break;
			case "D":
				note = "2";
				break;
			case "E":
				note = "3";
				break;
			case "F":
				note = "4";
				break;
			case "G":
				note = "5";
				break;
			case "A":
				note = "6";
				break;
			case "B":
				note = "7";
				break;
        }
        Console.Write("{0} ", note);
    }
}


//音阶类
class Scale : Expression
{
 	public override void Excute(string key,double value)
    {
    	string scale = "";
    	switch(Convert.ToInt32(vlaue))
        {
        	case 1:
				note = "低音";
				break;
			case 2:
				note = "中音";
				break;
			case 3:
				note = "高音";
				break;
			
        }
        Console.Write("{0} ", note);
    }
}


//客户端代码
static void Main(string[] args)
{
    PlayContext context = new PlayContext();
    console.WriteLine("上海滩: ");
    context.PlayText = " O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ";
    Expression expression = null;
    try
    {
        while (context.PlayText.Length > 0)
        {
            string str = context.PlayText.Substring(0,1);
            switch (str)
            {
                case "O":
                    expression = new Scale();
                    break;
                case "C":
                case "D":
                case "E":
                case "F":
                case "G":
                case "A":
                case "B":
                case "P":
                    expression = new Note();
                    break;
            }
            
            expression.Interpret(context);
            
        }
    }
    catch(Exception ex)
    {
        Console.WreteLine(ex.Message);
    }
    Console.Read();
}

//结果
上海滩:
中音 356352356 高音 1 中音 65132

三十一.访问者模式
创建型模式

隐藏了这些类的实例是如何被创建和放在一起,整个系统关于这些对象所知道的是由抽象类定义的接口。这样,创建型模式在创建了什么、谁创建它、他是怎么被创建的,以及何时创建这些方面提供了很大的灵活性。

结构型模式

行为型模式

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值