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

简介: 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();


23种设计模式【C#代码举例】(下):https://developer.aliyun.com/article/1556292

相关文章
|
4天前
|
开发框架 数据可视化 C#
|
4天前
|
设计模式 存储 C#
|
1月前
|
XML 开发框架 .NET
【.NET Core】常见C#代码约定
【.NET Core】常见C#代码约定
21 5
|
10天前
|
设计模式 C#
技术经验分享:C#设计模式
技术经验分享:C#设计模式
|
12天前
|
设计模式 Java
Java中设计模式及举例代码
Java中设计模式及举例代码
10 0
|
2月前
|
程序员 C# Python
100行python代码,轻松完成贪吃蛇小游戏_c#游戏100行代码(2)
100行python代码,轻松完成贪吃蛇小游戏_c#游戏100行代码(2)
|
1月前
|
JavaScript 前端开发 C#
初识Unity——创建代码、场景以及五个常用面板(创建C#代码、打开代码文件、场景的创建、Project、Hierarchy、Inspector、Scene、Game )
初识Unity——创建代码、场景以及五个常用面板(创建C#代码、打开代码文件、场景的创建、Project、Hierarchy、Inspector、Scene、Game )
23 0
|
2月前
|
存储 程序员 C#
100行python代码,轻松完成贪吃蛇小游戏_c#游戏100行代码
100行python代码,轻松完成贪吃蛇小游戏_c#游戏100行代码
|
2月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。