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

相关文章
|
2月前
|
缓存 C# Windows
C#程序如何编译成Native代码
【10月更文挑战第15天】在C#中,可以通过.NET Native和第三方工具(如Ngen.exe)将程序编译成Native代码,以提升性能和启动速度。.NET Native适用于UWP应用,而Ngen.exe则通过预编译托管程序集为本地机器代码来加速启动。不过,这些方法也可能增加编译时间和部署复杂度。
116 2
|
3月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
2月前
|
设计模式 算法 数据库连接
PHP中的设计模式:提高代码的可维护性和扩展性
【10月更文挑战第13天】 本文将探讨PHP中常见的设计模式及其在实际项目中的应用。通过对比传统编程方式,我们将展示设计模式如何有效地提高代码的可维护性和扩展性。无论是单例模式确保类的单一实例,还是观察者模式实现对象间的松耦合,每一种设计模式都为开发者提供了解决特定问题的最佳实践。阅读本文后,读者将能更好地理解和应用这些设计模式,从而提升PHP编程的效率和质量。
|
2月前
|
设计模式 安全 Java
C# 一分钟浅谈:设计模式之单例模式
【10月更文挑战第9天】单例模式是软件开发中最常用的设计模式之一,旨在确保一个类只有一个实例,并提供一个全局访问点。本文介绍了单例模式的基本概念、实现方式(包括饿汉式、懒汉式和使用 `Lazy&lt;T&gt;` 的方法)、常见问题(如多线程和序列化问题)及其解决方案,并通过代码示例详细说明了这些内容。希望本文能帮助你在实际开发中更好地应用单例模式,提高代码质量和可维护性。
36 1
|
2月前
|
C#
C# 图形验证码实现登录校验代码
C# 图形验证码实现登录校验代码
84 2
|
2月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP开发领域,设计模式是解决常见问题的高效方案集合。它们不是具体的代码,而是一种编码和设计经验的总结。单例模式作为设计模式中的一种,确保了一个类仅有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的基本概念、实现方式及其在PHP中的应用。
单例模式在PHP中的应用广泛,尤其在处理数据库连接、日志记录等场景时,能显著提高资源利用率和执行效率。本文从单例模式的定义出发,详细解释了其在PHP中的不同实现方法,并探讨了使用单例模式的优势与注意事项。通过对示例代码的分析,读者将能够理解如何在PHP项目中有效应用单例模式。
|
3月前
|
设计模式 算法 数据库连接
PHP中的设计模式:提高代码的可维护性与扩展性
设计模式在PHP开发中至关重要,如单例模式确保类仅有一个实例并提供全局访问点,适用于管理数据库连接或日志记录。工厂模式封装对象创建过程,降低系统耦合度;策略模式定义算法系列并使其可互换,便于实现不同算法间的切换。合理选择设计模式需基于需求分析,考虑系统架构,并通过测试驱动开发验证有效性,确保团队协作一致性和代码持续优化。设计模式能显著提升代码质量,解决开发中的设计难题。
34 8
|
3月前
|
设计模式 算法 PHP
PHP中的设计模式:提升代码的灵活性与可维护性
在本文中,我们将深入探讨PHP编程语言中的一种重要概念——设计模式。设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它代表了最佳的实践,被有经验的面向对象的软件开发人员所采用。本文将通过具体的实例,展示如何在PHP项目中应用设计模式,以提高代码的灵活性和可维护性。无论你是PHP初学者还是经验丰富的开发者,都能从中获得有价值的见解。
|
3月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入探索与实践在软件开发的广袤天地中,PHP以其独特的魅力和强大的功能,成为无数开发者手中的得力工具。而在这条充满挑战与机遇的征途上,设计模式犹如一盏明灯,指引着我们穿越代码的迷雾,编写出更加高效、灵活且易于维护的程序。今天,就让我们聚焦于设计模式中的璀璨明珠——策略模式,深入探讨其在PHP中的实现方法及其实际应用价值。
策略模式,这一设计模式的核心在于它为软件设计带来了一种全新的视角和方法。它允许我们在运行时根据不同情况选择最适合的解决方案,从而极大地提高了程序的灵活性和可扩展性。在PHP这门广泛应用的编程语言中,策略模式同样大放异彩,为开发者们提供了丰富的创作空间。本文将从策略模式的基本概念入手,逐步深入到PHP中的实现细节,并通过一个具体的实例来展示其在实际项目中的应用效果。我们还将探讨策略模式的优势以及在实际应用中可能遇到的挑战和解决方案,为PHP开发者提供一份宝贵的参考。
|
3月前
|
设计模式 存储 数据库连接
探索PHP中的设计模式:提高代码的可维护性与扩展性
本文将深入探讨PHP中常用的设计模式,包括单例模式、工厂模式和观察者模式。通过具体的代码示例,展示如何在实际项目中应用这些设计模式,以提高代码的可维护性与扩展性。无论你是PHP初学者还是有一定经验的开发者,都可以通过本文的学习,提升你的编程技巧和项目架构能力。