23种设计模式【C#代码举例】

第一章 简单工厂模式

简单工厂:对象实例化的工具类;
工厂模式:工厂接口(一个实例化方法),若干子类通过实现父类实例化方法,实例化相应类别的对象;
抽象工厂模式:工厂接口(多个实例化方法,适用于被实例化的对象有多个类别约束),若干子类通过实现父类实例化方法(多个方法),实例化相应类别的对象;
+public -private #protected
接口表示:<> 和棒棒糖法
继承:实线+空心三角
实现:虚线+空心三角 ------------△
关联:实线+箭头 >
依赖:虚线+箭头 ------------>
聚合:菱形+实线+箭头 ◇
>
合成:实心菱形+实线+箭头 ◆
>

第二章 策略模式

定义了算法家族,分别封装起来,让他们之间可以互相转换,此模式让算法的变化,不会影响到使用算法的客户。

    //抽象算法类
    public abstract class CashSuper
    {
        public abstract double GetResult(double money);
    }

    //具体算法类:正常
    public class CashNormal: CashSuper
    {
        public CashNormal()
        {
        }

        public override double GetResult(double money)
        {
            Console.WriteLine("算法A实现");
            return money;
        }
    }
    //具体算法类:打折
    public class CashRebate : CashSuper
    {
        public CashRebate(double discount)
        {
            Discount = discount;
        }

        public double Discount { get; set; }
        public override double GetResult(double money)
        {
            Console.WriteLine("算法B实现");
            return money * Discount;
        }
    }
    //具体算法类:返现

    public class CashReturn : CashSuper
    {
        public double Interval { get; set; }
        public double Rebate{ get; set; }

        public CashReturn(double interval, double rebate)
        {
            Interval = interval;
            Rebate = rebate;
        }

        public override double GetResult(double money)
        {
            Console.WriteLine("算法C实现");
            double result = (money%Interval)*Rebate;
            return result;
        }
}

感觉策略模式和工厂模式挺像,都是一个接口,若干子类,子类执行一个方法;但是用处不同,工厂模式是实例化对象用的,策略模式是实现相应算法用的;

第三章 单一职责原则

就一个类而言,应该仅有一个引起他变化的原因;

第四章 开放——封闭原则

软件实体(类,模块,函数)。应该可以扩展(开放),但是不可修改(封闭)。
面对需求,对程序的改动是通过增加行的代码,而不是修改现有的代码;

第五章 依赖倒转原则

高层模块不应该依赖低层模块,两个都应该依赖抽象;
抽象不应该依赖细节,细节应该依赖抽象;
举例:业务模块(高层),数据库模块(底层);不能因为数据库从mysql换成sql server,而对原有业务模块而大改特改。

里氏代换原则:子类必须能替换掉他们的父类型;
只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能被真正复用,而子类也能够在父类基础上增加新的行为。65

第六章 装饰模式

动态的给对象添加一些额外职责,就增加功能来说,装饰模式比生成子类更加灵活。

 //人
    public class Person
    {
        public Person() { }
        public string? Name { get; set; }
        public Person(string name)
        {
            Name = name;
        }
        public virtual void Show()
        {
            Console.WriteLine("装扮的{0}", Name);
        }
    }
    //服饰
    public class Finery : Person
    {
        protected Person? componet { get; set; }

        public void Decorate(Person componet)
        {
            this.componet = componet;
        }
        public override void Show()
        {
            if(componet != null)
            {
                componet.Show();
            }  
        }
    }

    //具体服饰:T型衫
    class TShirts : Finery
    {
        public override void Show()
        {
            Console.WriteLine("T型衫");
            base.Show();
        }
    }
    //具体服饰:大垮裤
    class BigTrouser : Finery
    {
        public override void Show()
        {
            Console.WriteLine("大垮裤");
            base.Show();
        }
}


//装扮代码
Person person = new Person("小菜");
Console.WriteLine("第一种装扮:");
TShirts ts= new TShirts();
BigTrouser bt = new BigTrouser();

ts.Decorate(person);
bt.Decorate(ts);
bt.Show();
Console.WriteLine("第二种装扮:");
bt.Decorate(person);
ts.Decorate(bt);
ts.Show();

想法:有点像俄罗斯套娃,更有点像穿衣服,只有第一次塞进去的是个人,后边都是塞进去的一个穿了一堆衣服的人;
最后执行show的时候,按装饰顺序执行各个装饰了类的show方法;

使用此模式的时机:向旧的类中添加新代码,新代码通常装饰或者说扩展了旧代码的核心行为;而这些新代码,可以使用某一个功能,也可以全部都,有点像穿衣服,穿一件或者全副武装;
另外注意:装饰模式的顺序很重要,关系到内裤内穿还是外穿;
比如文本过滤和加密,先加密,后过滤,这个顺序是有问题的。应该,先过滤,再加密;

第七章 代理模式

为其他对象提供一种代理,以控制对这个对象的访问;
远程代理:通过代理感觉是在本地访问一样;
虚拟代理:通过代理感觉好像是真实加载出来的一样,其实因为害怕加载太费时间,早已经加载好了,等你用呢。
安全代理:控制对象访问权限,通过代理没有权限访问的东西压根就不会出现。
智能指引:调用真实对象时,代理处理另外一些事情。需要代理,代理才会机智的出现。

//代理接口
    public interface GiveGift
    {
        void GiveDolls();
    }
    //被访问对象
    class Pursuit: GiveGift
    {
        SchoolGirl mm;

        public Pursuit(SchoolGirl mm)
        {
            this.mm = mm;
        }

        public void GiveDolls()
        {
            Console.WriteLine("{0},送你洋娃娃",mm.name);
        }
    }
    class SchoolGirl
    {
        public string name { get; set; }
    }
    class Proxy : GiveGift
    {
        public Proxy(SchoolGirl mm)
        {
            gg = new Pursuit(mm);
        }

        Pursuit? gg { get; set; }


        public void GiveDolls()
        {
            gg.GiveDolls();
        }
}

//使用代理模式
SchoolGirl mm = new SchoolGirl();
mm.name = "阿娇";
Proxy proxy=new Proxy(mm);
proxy.GiveDolls();

第八章 工厂方法 91

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类;

    //雷锋
    public class LeiFeng
    {
        public void DoWell()
        {
            Console.WriteLine("做好事...");
        }
    }
    //大学毕业生:学雷锋
    public class Undergraduate : LeiFeng { }
    //社区工作者:学雷锋
    public class Volunteer : LeiFeng { }
    //雷锋工厂接口
    public interface IFactory
    {
        LeiFeng CreateLeiFeng();
    }
    //雷锋工厂:毕业生
    public class UndergraduateFactory : IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Undergraduate();
        }
    }
    //雷锋工厂:社区工作者
    public class VolunteerFactory : IFactory
    {
        public LeiFeng CreateLeiFeng()
        {
            return new Volunteer();
        }
    }
//如果想创建新雷锋。就创建新的雷锋子类和新的雷锋工厂;

第九章 原型模式 102

原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

public class Resume : ICloneable
    {
        public string? Name { get; set; }
        public string? Sex { get; set; }
        public string? Age { get; set; }
        public string? School { get; set; }
        public string? Company { get; set; }

        public Resume(string? name, string? sex, string? age, string? school, string? company)
        {
            Name = name;
            Sex = sex;
            Age = age;
            School = school;
            Company = company;
        }
        public void Display()
        {
            Console.WriteLine("个人信息:{0},{1},{2}",Name,Sex,Age);
            Console.WriteLine("经历:{0},{1}", School, Company);
        }

        public object Clone()
        {
            return(Object)this.MemberwiseClone();
        }
}
//使用原型模式
Resume a = new Resume("大鹏", "男", "22", "铁道学院", "新展信科技");
Resume b = (Resume)a.Clone();
b.Name = "李文";
b.Sex = "女";
a.Display();
b.Display();

MemberviseClone方法是浅复制,不能能复制引用类型字段;
关于深复制方法有多重实现方式,以后探讨;

第十章 模板方法模式

定义一个操作中的算法的骨架,将一些步骤延迟到子类。模板方法使得子类可以改变一个算法的结构,即可以重新定义该算法的某些特定步骤。

public class TestPaper
    {
        public string _Answer1 { get; set; }
        public string _Answer2 { get; set; }
        public string _Answer3 { get; set; }
        public void question1()
        {
            Console.WriteLine("1.一个选择题,或者一个算法");
            Console.WriteLine("1.答案:{0}", _Answer1);
        }
        public void question2()
        {
            Console.WriteLine("2.一个选择题,或者一个算法");
            Console.WriteLine("2.答案:{0}", _Answer2);
        }
        public void question3()
        {
            Console.WriteLine("3.一个选择题,或者一个算法");
            Console.WriteLine("3.答案:{0}", _Answer3);
        }
        public virtual void Answer1(string answer)
        {
            _Answer1=answer;
        }
        public virtual void Answer2(string answer)
        {
            _Answer2 = answer;
        }
        public virtual void Answer3(string answer)
        {
            _Answer3 = answer;
        }
    }
    public class TestPaperA: TestPaper
    {
        public string name { get; set; }
        public TestPaperA(string name) 
        {
            this.name = name;
            Console.WriteLine("【{0}】同学开始答题",name);
        }

        public  override void Answer1(string answer)
        {
            Console.WriteLine("思考一下");
            base.Answer1(answer);
        }
        public override void Answer2(string answer)
        {
            Console.WriteLine("思考一下");
            base.Answer2(answer);
        }
        public override void Answer3(string answer)
        {
            Console.WriteLine("思考一下");
            base.Answer3(answer);
        }

  }

//使用
TestPaper test = new TestPaperA("张三");
test.Answer1("a");
test.question1();
test.Answer2("aa");
test.question2();
test.Answer3("aaa");
test.question3();

第十一章 迪米特法则

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

第十二章 外观模式

为系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口是的这一子系统更加容易使用;
适用时机:通过外观类,给乱七八糟的子系统接口,提供一些统一的对外接口,对接口需求者不需要了解的执行或数据,只需要在外观类内部执行完毕即可;

    //子系统1234
    public class SubSystemOne
    {
        public void MethodOne()
        {
            Console.WriteLine("子系统一:方法1");
        }
    }
    public class SubSystemTwo
    {
        public void MethodTwo()
        {
            Console.WriteLine("子系统二:方法2");
        }
    }
    public class SubSystemThree
    {
        public void MethodThree()
        {
            Console.WriteLine("子系统三:方法3");
        }
    }
    public class SubSystemFour
    {
        public void MethodFour()
        {
            Console.WriteLine("子系统四:方法4");
        }
    }
    //外观类
    public class Facade
    {
        public SubSystemOne? one { get; set; }
        public SubSystemTwo? two { get; set; }
        public SubSystemThree? three { get; set; }
        public SubSystemFour? four { get; set; }
        public Facade()
        {
            this.one = new SubSystemOne();
            this.two = new SubSystemTwo();
            this.three = new SubSystemThree();
            this.four = new SubSystemFour();
        }
        public void MethodA()
        {
            Console.WriteLine("方法组A:----");
            one.MethodOne();
            two.MethodTwo();
            three.MethodThree();
        }
        public void MethodB()
        {
            Console.WriteLine("方法组B:---");
            one.MethodOne();
            two.MethodTwo();
           
            four.MethodFour();
        }
    }

//使用
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();

第十三章 建造者模式

将一个复杂对象的构建和他的表示分离,使得同样的构建过程可以构建不同的表示。

 //抽象建造者
    abstract class PersonBuilder
    {
        protected Graphics g;
        protected Pen p;
        public PersonBuilder(Graphics g, Pen p)
        {
            this.g = g;
            this.p = p;
        }
        public abstract void buildHead();
        public abstract void buildBody();
        public abstract void buildArmLeft();
        public abstract void buildArmRight();
        public abstract void buildLegLeft();
        public abstract void buildLegRight();
    }

    //具体建造者,瘦人
    class PersonThinBuilder : PersonBuilder
    {
        public PersonThinBuilder(Graphics g, Pen p) : base(g, p)
        {
        }

        public override void buildArmLeft()
        {
            g.DrawLine(p,60,50,40,100);
        }

        public override void buildArmRight()
        {
            g.DrawLine(p, 70,50,90,100);
        }

        public override void buildBody()
        {
            g.DrawRectangle(p, 60, 50, 10, 50);
        }

        public override void buildHead()
        {
            g.DrawEllipse(p,50,20,30,30);
        }

        public override void buildLegLeft()
        {
            g.DrawLine(p,60,100,45,150);
        }

        public override void buildLegRight()
        {
            g.DrawLine(p, 70,100,85,150);
        }
    }
    //指挥者:也叫组装者
    class PersonDirector
    {
        private PersonBuilder pb;

        public PersonDirector(PersonBuilder pb)
        {
            this.pb = pb;
        }
        public void CreatePerson()
        {
            pb.buildHead();
            pb.buildBody();
            pb.buildArmLeft();
            pb.buildArmRight();
            pb.buildLegLeft();
            pb.buildLegRight();
        }
}

//
Pen p = new Pen(Color.Yellow);
PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(),p);
PersonDirector pdthin = new PersonDirector(ptb);
pdthin.CreatePerson();

第十四章 观察者模式 149

又叫发布订阅模式;
定义了一对多的依赖关系,让多个观察者对象同时监听某个主题对象。在主题对象状态发生变化时,会通知相应的所有观察者,是他们能够自动更新自己

    //通知者接口
    public interface Subject
    {
        void Attach(Observer observer);
        void Detach(Observer observer);
        void Notify();
        public string? SubjectState { get; set; }
    }
    //具体通知者
    class Boss : Subject
    {
        //同事列表
        public IList<Observer> observers=new List<Observer>();
        public string? action { get; set; }
        public string? SubjectState { get; set; }
        //增加
        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();
            }
        }

        
    }
    class Secretary : Subject
    {
        //同事列表
        public IList<Observer> observers = new List<Observer>();
        public string? action { get; set; }
        public string? SubjectState { get; set; }
        //增加
        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 abstract class Observer
    {
        public string name { get; set; }
        public Subject sub { get; set; }
        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);
        }
    }
    class NBAObserver : Observer
    {
        public NBAObserver(string name, Secretary sub) : base(name, sub)
        {

        }

        public override void Update()
        {
            Console.WriteLine("{0},{1},关闭NBA球赛,继续工作!", sub.SubjectState, name);
        }
    }
///测试代码
Boss boss = new Boss();
boss.Attach(new StockObserver("x", boss));
boss.Attach(new StockObserver("y", boss));
boss.Attach(new StockObserver("z", boss));

boss.SubjectState = "老板来了,";
boss.Notify();

事件委托实现
观察者和通知者互相不知道,由客户端决定通知谁。去掉了抽象观察类。

delegate void EventHandler();
    //通知者接口
    public interface Subject
    {
        void Notify();
        public string? SubjectState { get; set; }
    }
    //具体通知者
    class Boss : Subject
    {
        public event EventHandler Update;
        public string? SubjectState { get; set; }
        public string? action { get; set; }

        //通知
        public void Notify()
        {  
                Update();       
        }
    }
    class Secretary : Subject
    {
        //同事列表
        public event EventHandler Update;
        public string? SubjectState { get; set; }
        public string? action { get; set; }

        //通知
        public void Notify()
        {
            Update();
        }

    }
    
    //具体观察者
    class StockObserver 
    {
        public string name { get; set; }
        public Subject sub { get; set; }
        public StockObserver(string name, Subject sub) 
        {
            this.name = name;
            this.sub=sub;
        }

        public  void CloseStock()
        {
            Console.WriteLine("{0},{1},关闭股票继续工作!",sub.SubjectState,name);
        }
    }
    class NBAObserver
    {
        public string name { get; set; }
        public Subject sub { get; set; }
        public NBAObserver(string name, Subject sub) 
        {
            this.name = name;
            this.sub = sub;
        }

        public void CloseNBA()
        {
            Console.WriteLine("{0},{1},关闭NBA球赛,继续工作!", sub.SubjectState, name);
        }
}
、、、测试代码
Boss boss = new Boss();
StockObserver so1 = new StockObserver("李四", boss);
NBAObserver so2 = new NBAObserver("张三", boss);

boss.Update += new EventHandler(so1.CloseStock);
boss.Update += new EventHandler(so2.CloseNBA);
boss.SubjectState = "我回来了";
boss.Notify();

第十五章 抽象工厂模式 167

提供一个创建一系列相关或者额相互依赖的对象的接口,而无需指定它们的具体的类;

    //数据实体
    public class DataUser
    {
        public DataUser(string name,string id)
        {
            Name = name;Id = id;
        }

        public string Name { get; set; }
        public string Id { get; set; }

    }
    public class DataDepartment
    {
        public DataDepartment(string deptname, string id)
        {
            Deptname = deptname;
            Id = id;
        }

        public string Deptname { get; set; }
        public string Id { get; set; }
    }
    //User操作接口
    public interface IUser
    {
        public void Insert(DataUser u);
        public DataUser Get();
    }
    //User操作具体类
    public class SqlserverUser : IUser
    {
        public DataUser Get()
        {
            Console.WriteLine("Sqlserver获取用户");
            return null;
        }

        public void Insert(DataUser u)
        {
            Console.WriteLine("Sqlserver添加用户");
            
        }
    }
    public class AccessUser : IUser
    {
        public DataUser Get()
        {
            Console.WriteLine("Access获取用户");
            return null;
        }

        public void Insert(DataUser u)
        {
            Console.WriteLine("Access添加用户");
        }
    }
    //Department操作接口
    public interface IDepartment
    {
        public void Insert(DataDepartment d);
        public DataDepartment Get();
    }
    //Department操作具体类
    public class SqlserverDepartment : IDepartment
    {
        public DataDepartment Get()
        {
            Console.WriteLine("Sqlserver获取部门");
            return null;
        }

        public void Insert(DataDepartment d)
        {
            Console.WriteLine("Sqlserver添加部门");
        }
    }
    public class AccessDepartment : IDepartment
    {
        public DataDepartment Get()
        {
            Console.WriteLine("Access获取部门");
            return null;
        }

        public void Insert(DataDepartment d)
        {
            Console.WriteLine("Access添加部门");
        }
    }
    //操作类工厂接口
    public interface IFactory
    {
        public IUser CreateUser();
        public IDepartment CreateDepartment();  
    }
    //操作类工厂的具体实现类
    class SqlserverFactory : IFactory
    {
        public IDepartment CreateDepartment()
        {
            return new SqlserverDepartment();
        }

        public IUser CreateUser()
        {
            return new SqlserverUser(); ;
        }
    }
    class AccessFactory : IFactory
    {
        public IDepartment CreateDepartment()
        {
            return new AccessDepartment();
        }

        public IUser CreateUser()
        {
            return new AccessUser(); ;
        }
}

--测试:换了工厂类factory,数据库访问则被更换;
DataUser user=new DataUser("张三","U01");
DataDepartment dept = new DataDepartment("财务部","D001");

//IFactory factory = new AccessFactory();
IFactory factory = new SqlserverFactory();
IUser iu= factory.CreateUser();
IDepartment idept= factory.CreateDepartment();

iu.Insert(user);
iu.Get();

idept.Insert(dept);
idept.Get();

缺点:增加一个表project;需要增加DataProject数据类。还需要增加三个操作类IProject,SQLserverProject,AccessProject,修改三个类,IFactory,SQLserverFactory,AccessFactory。
更换数据库是方便,但是实现过程,每增加一个表,要增加或更改的地方太多了。

关于抽象工厂的优化:用简单工厂完成factory的部分;一个DataAccess工具类足矣(不同数据库的相应表的操作类实例化);略;

对抽象工厂优秀的优化方案:反射+抽象工厂
Assembly.Load(“程序集名称”).CreateInstance(命名空间.类名称);
常规活的实例的方法

IUser iu=new SqlserverUser();

反射获取实例方法

IUser iu=(IUser)Assembly.Load(“AbsFactory”).CreateInstance(“AbsFactory.Sqlserver”);

实现后的DataAccess如下;

class DataAccess
    {
        private static readonly string AssemblyName = "AbsFactory";
        private static readonly string db = "sqlserver";
        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);
        }
}

如果增加了一个表Project。则DataAccess增加一个CreateProject方法;增加三个Project相关类;

更优化的方法:
将数据库字符串放在配置文件中。这样改变数据库,只需要改变配置文件,而不需要重新编译程序;这样会少了一些关于数据库选择Switch语句;

第十六章 状态模式

当一个对象状态改变时,允许改变起行为,这个对象看起来像是改变了其类;
优点:将于特定状态相关的行为局部化,并且将不同状态的行为分割开来;
使用时机:一个对象的行为取决于他的状态,并且它必须在运行时时刻根据状态改变行为,此时可以考虑使用状态模式。

每个状态对应一个状态类,改变状态就是改变了状态类。

public class Work
    {
        public double Hour { get; set; }
        public bool Finish { get; set; }
        public State State { get; set; }
        public Work()
        {
            State=new ForenoonState();

        }
        public void SetState(State s)
        {
            State = s;
        }
        public void WriteProgram()
        {
            State.WriteProgram(this);
        }
    }
    //抽象状态类
    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 >=12&&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 > 13)
            {
                Console.WriteLine("当前时间:{0}点,上午工作,精神还可以。", w.Hour);
            }
            else
            {
                w.SetState(new ForenoonState());
                w.WriteProgram();
            }
        }
}

--代码测试
//状态模式
Work w = new Work();
w.Hour = 9;
w.WriteProgram();
w.Hour = 10;
w.WriteProgram();
w.Hour = 11;
w.WriteProgram();
w.Hour = 12;
w.WriteProgram();
w.Hour = 13;
w.WriteProgram();
w.Hour = 14;
w.WriteProgram();
w.Hour = 15;
w.WriteProgram();
w.Hour = 16;
w.WriteProgram();

第十七章 适配器模式 197

将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。

适配器分类:
类适配器:通过多重继承对一个接口与另一个接口进行匹配。很多语言不支持多重继承。
对象适配器:主要的适配器类别。

使用时机:两个类所做事情相同或类似,单具有的接口不同;而双方都不易修改;

   //目标,客户需求接口

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

//测试代码
Target target = new Adapter();
target.Request();

第十八章 备忘录模式 206

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以讲该对象恢复到原先保存的状态。
我首先想到的就是单机游戏的存档。
发起人:创建备忘录memento;
备忘录memento:存储对象状态;
管理者:保存备忘录;

场合:功能复杂,需要维护或记录属性历史的类,或者需要保存属性只是众多属性中一部分。可以更具备忘录保存的信息还原到前一状态。

 //发起人
    public class Originator
    {
        public string State { get; set; }
        public Memento CreateMemento()
        {
            return new Memento(State);
        }
        public void SetMemento(Memento memento)
        {
            State = memento.State;
        }
        public void Show()
        {
            Console.WriteLine("State={0}",State);
        }
    }
    //备忘录
    public class Memento
    {
        public String State { get; set; }
        public Memento(string state)
        {
            State = state;
        }
    }
    //管理者
    public class Caretaker
    {
        public Memento memento { get; set; }
}
//测试代码
Originator o = new Originator();
o.State = "On";
o.Show();

Caretaker caretaker = new Caretaker();
caretaker.memento = o.CreateMemento();

o.State = "Off";
o.Show();

o.SetMemento(caretaker.memento);
o.Show();

第十九章 组合模式 215

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

使用的时机:需求是提现部分与整体的层次结构,并忽略组合对象与单个对象的不同,统一使用组合结构中的所有对象时,考虑使用组合模式;

abstract class Componet
    {
        protected Componet(string name)
        {
            Name = name;
        }

        public abstract string Name { get; set; }
        public abstract void Add(Componet c);
        public abstract void Remove(Componet c);
        public abstract void Display(int depth);
    }
    class Leaf : Componet
    {
        public Leaf(string name):base(name)
        {
        }

        public override string Name { get; set; }

        public override void Add(Componet c)
        {
            Console.WriteLine("Can't add to a leaf");
        }

        public override void Display(int depth)
        {

            Console.WriteLine(new String('-',depth)+Name);
        }

        public override void Remove(Componet c)
        {
            Console.WriteLine("Can't remove from a leaf");
        }
    }
    class Composite : Componet
    {
        public List<Componet> children { get; set; }= new List<Componet>();
        public Composite(string name) : base(name)
        {
        }

        public override string Name { get; set; }

        public override void Add(Componet c)
        {
            children.Add(c);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + Name);
            foreach(var c in children)
            {
                c.Display(depth + 2);
            }

        }

        public override void Remove(Componet c)
        {
            children.Remove(c);
        }
}


//测试代码
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 comp1 = new Composite("composite XY");
comp1.Add(new Leaf("Leaf XYA"));
comp1.Add(new Leaf("Leaf XYB"));
root.Add(comp1);
root.Display(0);

第二十章 迭代模式

提供一种方法,顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

//迭代器抽象类
    abstract class Iterator
    {
        public abstract object First();
        public abstract object Next();
        public abstract bool IsDone();
        public abstract object CurrentItem();
    }
    //聚集抽象类
    abstract class Aggregate
    {
        public abstract Iterator CreaeteIterator();
    }
    //具体迭代类,继承抽象迭代器
    class ConcreteIterator : Iterator
    {
        private ConcreteAggregate aggregate;
        private int current=0;

        public ConcreteIterator(ConcreteAggregate aggregate)
        {
            this.aggregate = aggregate;
        }

        public override object CurrentItem()
        {
           return aggregate[current];
        }

        public override object First()
        {
            return aggregate[0];
        }

        public override bool IsDone()
        {
            return current>=aggregate.Count;
        }

        public override object Next()
        {
            object ret = null;
            current ++;
            if (current < aggregate.Count)
            {
                ret= aggregate[current];
            }
            return ret;
        }
    }

    //具体聚集类,继承Aggieregate
    class ConcreteAggregate : Aggregate
    {
        private IList<Object> items = new List<Object>();
        public int Count { get { return items.Count; } }
        public Object this[int index] { 
            get { return items[index]; } 
            set { items.Insert(index, value); } 
        }
        public override Iterator CreaeteIterator()
        {
            throw new NotImplementedException();
        }
}

//代码测试
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "大鸟0";
a[1] = "大鸟1";
a[2] = "大鸟2";
a[3] = "大鸟3";
a[4] = "大鸟4";
Iterator i = new ConcreteIterator(a);
object item = i.First();
while (!i.IsDone())
{
    Console.WriteLine("买票:{0}",i.CurrentItem());
    i.Next();
}

现在泛滥的for应用,使得迭代模式在很多集合中已经实现。所以自定义的迭代模式极少。甚至有人呼吁取消迭代模式;

第二十一章 单例模式 236

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

 //多线程时的单例
    public class Singleton
    {
        private static Singleton? instance;
        private readonly static object syncRoot=new object();
        private Singleton()
        {

        }
        public static Singleton GetInstance()
        {
            //双重锁,去掉外层if也可以,就变成了单层锁
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            
            return instance;
        }
}

静态初始化

 //静态初始化,要点就是sealed(阻止派生)和readonly(一次创建)
    public sealed  class Singleton
    {
        private static readonly Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton GetInstance()
        {
            return instance;
        }
    }

第二十二章 桥接模式 247

桥接模式:将抽象部分与它的实现部分分离,使他们都可以独立变化;

 //手机软件,抽象类
   public abstract class HandsetSoft
    {
        public abstract void Run();
    }
    //手机软件,具体类
    public class HandsetGame : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("运行手机游戏");
        }
    }
    public class HandsetAddressList : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("运行手机通讯录");
        }
    }
    //手机品牌抽象类
    abstract class HandsetBrand
    {
        public HandsetSoft soft { get; set; }
        public abstract void Run();
    }
    //具体的手机品牌M,N
    class HandSetBrandM : HandsetBrand
    {
        public override void Run()
        {
            soft.Run();
        }
    }
    class HandSetBrandN : HandsetBrand
    {
        public override void Run()
        {
            soft.Run();
        }
}

测试代码

HandsetBrand ab = new HandSetBrandN();
ab.soft = new HandsetGame();
ab.Run();
ab.soft= new HandsetAddressList();
ab.Run();

ab = new HandSetBrandM();
ab.soft = new HandsetGame();
ab.Run();
ab.soft = new HandsetAddressList();
ab.Run();

如果新增了Mp3,则只需要新增一个类

public class HandsetMp3 : HandsetSoft
    {
        public override void Run()
        {
            Console.WriteLine("运行手机Mp3");
        }
    }

第二十三章 命令模式 261

将一个请求封装为一个对象,从而使你可用不同的请求对客户参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。

   //接受者:烤串的人;
    class Receiver
    {
        public void Action()
        {
            Console.WriteLine("执行请求");
        }
    }
    //抽象命令
    abstract class Command
    {
        public Receiver receiver { get; set; }
        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 Invoker
    {
        public Command command { get; set; }
        public void ExecuteCommand()
        {
            command.Execute();
        }
}

执行代码 客户

Receiver r = new Receiver();
Command c = new ConcreteCommand(r);
Invoker i = new Invoker();

i.command=c;
i.ExecuteCommand();

整个过程就是:客户喊了个服务员,制定了一个命令。服务员带着命令,让执行者执行命令;

第二十四章 责任链模式

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的偶合。将这个对象连成一个链,并沿着这条链传递改请求,直到有一个对象处理它 。

 //申请
    class Request
    {
        public string requestType { get; set; }
        public string requestContent { get; set; }
        public int requestNumber { get; set; }

        public Request(string requestType, string requestContent, int requestNumber)
        {
            this.requestType = requestType;
            this.requestContent = requestContent;
            this.requestNumber = requestNumber;
        }
    }
    //管理者
    abstract class Manager
    {
        public  string Name { get; set; }
        //上级
        public  Manager superior { get; set; }

        protected Manager(string name)
        {
            Name = name;
        }

        protected Manager(Manager superior)
        {
            this.superior = superior;
        }
        abstract public void RequestApplications(Request request);
    }
    //经理
    class CommonManager : Manager
    {
        public CommonManager(string name) : base(name)
        {
        }

        public override void RequestApplications(Request request)
        {
            if (request.requestType == "请假" && request.requestNumber <= 2)
            {
                Console.WriteLine( "{0}:{1}{2}天被批准!",Name,request.requestContent,request.requestNumber);
            }
            else
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    //总监
    class MajorManager : Manager
    {
        public MajorManager(string name) : base(name)
        {
        }

        public override void RequestApplications(Request request)
        {
            if (request.requestType == "请假" && request.requestNumber <= 5)
            {
                Console.WriteLine("{0}:{1}{2}天被批准!", Name, request.requestContent, request.requestNumber);
            }
            else
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    //总经理
    class BossManager : Manager
    {
        public BossManager(string name) : base(name)
        {
        }

        public override void RequestApplications(Request request)
        {
            if (request.requestType == "请假")
            {
                Console.WriteLine("{0}:{1}{2}天被批准或者拒绝!", Name, request.requestContent, request.requestNumber);
            }
            else if (request.requestType == "加薪")
            {

                Console.WriteLine("{0}:{1}数量{2}被批准或者拒绝!", Name, request.requestContent, request.requestNumber);

            }
           
        }
}

//测试代码
CommonManager jinli = new CommonManager("锦鲤经理");
MajorManager major = new MajorManager("卡卡总监");
BossManager boss = new BossManager("博士老总");
jinli.superior = major;
major.superior = boss;

Request request = new Request("请假","小菜请假",3);
jinli.RequestApplications(request);

上面的管理者只列出了上级;
关于请求的发起来源及提交下级的情况应该怎么记录,做出思考;发起来源可以放在请求里;提交来源可以放在请求里,流程经手人都可以放在请求里按顺序存放。

第二十五章 中介者模式

中介者,也叫调停者。
中介者模式:用一个中介对象封装一些列的对象交互。中介者使各对象不要显式地相互作用,从而使其耦合松散,而且可以独立改变他们之间的交互。

//抽象中介者:联合国机构
    abstract class UnitedNations
    {
        //声明
        public abstract void Declare(string message,Country colleague);
    }
    //具体的中介 安理会
    class UnitedNationsSecurityCouncil : UnitedNations
    {
        public USA c1;
        public Iraq c2;
        public override void Declare(string message, Country colleague)
        {
            if (colleague == c1)
            {
                c2.GetMessage(message);
            }
            else if(colleague == c2)
            {
                c1.GetMessage(message);
            }
        }
    }

    //需要被中介的抽象类:国家
    abstract class Country
    {
       
        public UnitedNations mediator { get; }

        protected Country(UnitedNations mediator)
        {
            this.mediator = mediator;
        }
       
    }
    //具体的国家类
    class USA : Country
    {
       
        public USA(UnitedNations mediator) : base(mediator)
        {
        }
        public void Declare(string message)
        {
            mediator.Declare(message, this);
        }
        public void GetMessage(string message)
        {
            Console.WriteLine("USA获得消息:"+message);
        }

    }
    class Iraq : Country
    {
        public Iraq(UnitedNations mediator) : base(mediator)
        {
           
        }
        public void Declare(string message)
        {
            mediator.Declare(message, this);
        }
        public void GetMessage(string message)
        {
            Console.WriteLine("伊拉克获得消息:" + message);
        }
}


//测试代码

UnitedNationsSecurityCouncil uni = new UnitedNationsSecurityCouncil();
USA usa = new USA(uni);
Iraq iraq = new Iraq(uni);

uni.c1=usa;
uni.c2=iraq;
usa.Declare("美国声明:我要打你了");
iraq.Declare("伊拉克声明:你可以试试");

最简单的就是1对1的中介模式;也可以是1对多模式;多对多模式我暂时没想出来;但是只要制定了规则,多对多按规则交互也是可以的。就是按规则在中间类内部进行了信息的交流。

第二十六章 享元模式

享元模式:运用共享技术有效支持大量细粒度的对象。

  //用户
    public class User
    {
        public string Name { get; set; }

        public User(string name)
        {
            Name = name;
        }
    }
    //抽象网站
    abstract class WebSite
    {
        public abstract void Use(User user);
    }
    //实际网站
    class ConcreteWebSite : WebSite
    {
        public string Name { get; set; }

        public ConcreteWebSite(string name)
        {
            Name = name;
        }

        public override void Use(User user)
        {
            Console.WriteLine("网站分类:{0} ;用户:{1}",Name ,user.Name);
        }
    }
    //网站工厂
    class WebSiteFactory
    {
        public Hashtable flyweights = new Hashtable();
        //获得网站分类
        public WebSite GetWebSiteCategory(string key)
        {
            if (!flyweights.ContainsKey(key))
            {
                flyweights.Add(key, new ConcreteWebSite(key));
            }
            return (WebSite)flyweights[key];
        }
        //获取网站个数
        public int GetWebSiteCount()
        {
            return flyweights.Count;
        }
}
//测试代码

WebSiteFactory factory = new WebSiteFactory();

WebSite w1= factory.GetWebSiteCategory("展品展示");
w1.Use(new User("小菜2"));
WebSite w2 = factory.GetWebSiteCategory("展品展示");
w1.Use(new User("小菜1"));
WebSite w3 = factory.GetWebSiteCategory("展品展示");
w1.Use(new User("小菜3"));
WebSite w4 = factory.GetWebSiteCategory("博客");
w1.Use(new User("小菜4"));
WebSite w5 = factory.GetWebSiteCategory("博客");
w1.Use(new User("小菜5"));
WebSite w6 = factory.GetWebSiteCategory("博客");
w1.Use(new User("小菜2"));
Console.WriteLine("网站分类总数:{0}",factory.GetWebSiteCount());

分类不同才是真的不同。账号不同就是根据账号区分一下数据。

第二十七章 解释器模式

解释器模式:给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

时机:一种特定类型的问题发生频率足够高,那么可能就值得将该问题各个实例表述为一个简单语言中的句子。这样就可以构成一个解释器,该解释器通过解释这些句子来解决该问题。
举例:正则表达式;

class Context
    {
        public Context(string input)
        {
            Input = input;
        }

        public string Input { get; set; }
        public string Output { get; set; }
    }
    //抽象表达式
    abstract class AbstractExpression
    {
        //解释器
        public abstract void Interpret(Context context);
       
        //执行:如有必要,可以有多个执行;
        public abstract void Excute(string key, string value);
    }

    //A解释器
    class AExpression : AbstractExpression
    {
        public override void Excute(string key, string value)
        {
            if (key == "A")
            {
                Console.WriteLine("A终端解释器:{0}-{1}", key, value);
            }
        }

        public override void Interpret(Context context)
        {
            {

                Dictionary<string, string> dict = new Dictionary<string, string>();
                for (int i = 0; i < context.Input.Length / 2; i++)
                {
                    string key = context.Input.Substring(2 * i, 1);
                    string value = context.Input.Substring(2 * i + 1, 1);
                    Excute(key, value);
                }
            }
        }
    }

    //B解释器
    class BExpression : AbstractExpression
    {
        public override void Excute(string key, string value)
        {
            if (key == "B")
            {
                Console.WriteLine("A终端解释器:{0}-{1}", key, value);
            }
        }

        public override void Interpret(Context context)
        {
            {

                Dictionary<string, string> dict = new Dictionary<string, string>();
                for (int i = 0; i < context.Input.Length / 2; i++)
                {
                    string key = context.Input.Substring(2 * i, 1);
                    string value = context.Input.Substring(2 * i + 1, 1);
                    Excute(key, value);
                }
            }
        }
}

//执行代码
Context context = new Context("A0B2C3A4B5A6B8B9A0AaBb");
AbstractExpression expression=new BExpression();
expression.Interpret(context);
Console.ReadLine();

解释器,文法规则的设计很重要。

第二十八章 访问者模式

表示一个作用于某对象结构中的各元素操作。他使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

//抽象被访问者
   public abstract class Person
    {
        public abstract void Accept(Action visitor);
    }
    public class Man : Person
    {
        public override void Accept(Action visitor)
        {
           
            visitor.VisitMan(this);
        }
    }
    public class WoMan : Person
    {
        public override void Accept(Action visitor)
        {
            visitor.VisitWoMan(this);
        }
    }

    //抽象提问
    public abstract class Action
    {
        public abstract void VisitMan(Man man);
        public abstract void VisitWoMan(WoMan woman);
    }
    //成功
    class Success : Action
    {
        public override void VisitMan(Man man)
        {
            Console.WriteLine("{0}{1}时,背后多半有一个伟大的女人!",man.GetType().Name,this.GetType().Name);
        }

        public override void VisitWoMan(WoMan woman)
        {
            Console.WriteLine("{0}{1}时,背后多半有一个失败的男人!", woman.GetType().Name, this.GetType().Name);
        }
    }
    //结婚
    class Merry : Action
    {
        public override void VisitMan(Man man)
        {
            Console.WriteLine("{0}{1}时,【有妻徒刑】开始执行!", man.GetType().Name, this.GetType().Name);
        }

        public override void VisitWoMan(WoMan woman)
        {
            Console.WriteLine("{0}{1}时,【爱情保险】开始生效!", woman.GetType().Name, this.GetType().Name);
        }
}

//测试代码
List<Console23Style.HK.Visitor.Person> ps = new List<Console23Style.HK.Visitor.Person>();
ps.Add(new Man());
ps.Add(new WoMan());
Success success = new Success();
Merry merry = new Merry();
foreach (Console23Style.HK.Visitor.Person p in ps)
{
    p.Accept(success);
    p.Accept(merry);
}

多一个话题,既需要多一个action的子类;对Person和其子类没有影响;


你可能感兴趣的:(设计模式,c#,java)