设计模式(一) 创建型设计模式与结构型设计模式

设计模式(一) 创建型设计模式

创建型设计模式:作用于对象的创建,将对象的创建与使用分离

一、 单例设计模式

用途:保证该类在系统之中只有一个实例,用以确保运行逻辑的正确性与使用效率。

饿汉单例模式(在没有调用之前就创建单例对象)

public class SingleHungry
{
    private SingleHungry() { }

    private static readonly SingleHungry _singleHungry= new SingleHungry();
    public static SingleHungry GetSingleHungry()
    {
        return _singleHungry;
    }
}

懒汉单例模式(在调用以后才进创建单例对象)

public class Single
{
    private Single() { }

    private static Single _single;
    public static Single GetSingle()
    {
        if (_single==null)
        {
            _single=new Single();
        }
        return _single;
    }
}

如果是多线程运行,那么可能创建多个对象,进而破坏了单例的情况。

修改如下,使用lock进行加锁

public class Single
{
    private Single() { }

    private static Single _single;

    private static object o = new object();
    public static Single GetSingle()
    {
        lock (o)
        {
            if (_single == null)
            {
                _single = new Single();
            }
            return _single;
        }
       
    }
}

说明

  1. 饿汉式优点:书写简单,避免了线程同步的问题
  2. 饿汉式缺点:类加载的时候就创建了对象,造成内存的浪费
  3. 懒汉式优点:实现了懒加载,不会造成内存的浪费
  4. 懒汉式缺点:只适合单线程使用,多线程会造成线程安全问题

二、工厂模式

(一) 简单工厂模式(不属于23种设计模式,使一种常见的设计习惯)

模板类图如下:

image-20230402165205024

特点:工厂方法决定了指定的产品的生产。这些产品都是抽象产品接口的实现

  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。

  • 具体产品:实现或者继承抽象产品的子类。

  • 具体工厂:提供了创建产品的方法,使用者通过该方法来获取产品。

加减运算执行的简单工厂模式
代码如下:

   public partial class Program
    {
        static void Main(string[] args)
        {
            string oper = "+";
            ICalculator calculator = CalFactory.GetCalculator(oper);
            double res = calculator.GetResult(0.3, 0.5);
        }
    }

    public class CalFactory
    {
        public static ICalculator GetCalculator(string oper)
        {
            ICalculator calculator = null;
            switch (oper)
            {
                case "+":
                    calculator = new Add();
                    break;
                case "-":
                    calculator = new Sub();
                    break;
            }
            return calculator;
        }
    }

    public interface ICalculator
    {
        double GetResult(double d1, double d2);
    }

    public class Add : ICalculator
    {
        public double GetResult(double d1, double d2)
        {
            return d1 + d2;
        }
    }

    public class Sub : ICalculator
    {
        public double GetResult(double d1, double d2)
        {
            return d1 - d2;
        }
    }

image-20230405011414767

针对当前模式面临的问题,一种小的弥补手段

  1. 在每个操作方法上使用特性
  2. 建立一个反射工厂,让特性与操作方法进行绑定
    public partial class Program
    {
        static void Main(string[] args)
        {
            string oper = "+";
            ReflectionFactory reflectionFactory = new ReflectionFactory();
            ICalFactory calFactory = reflectionFactory.GetFac(oper);
            ICalculator calculator = calFactory.GetCalculator();
            double res = calculator.GetResult(0.2, 0.3);
        }
    }

    public class OperToFactory : Attribute
    {
        public string Oper { get; }
        public OperToFactory(string s)
        {
            this.Oper = s;
        }
    }

    public class ReflectionFactory
    {
        Dictionary<string, ICalFactory> dic = new Dictionary<string, ICalFactory>();
        
        public ReflectionFactory()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            foreach (var item in assembly.GetTypes())
            {
                if (typeof(ICalFactory).IsAssignableFrom(item) && !item.IsInterface)
                {
                    OperToFactory otf = item.GetCustomAttribute<OperToFactory>();
                    if (otf.Oper != null)
                    {
                        dic[otf.Oper] = Activator.CreateInstance(item) as ICalFactory;
                    }
                }
            }
        }

        public ICalFactory GetFac(String s)
        {
            if (dic.ContainsKey(s))
            {
                return dic[s];
            }
            else
            {
                return null;
            }
        }

    }

    public interface ICalculatory
    {
        ICalculator GetCalculator();
    }


    [OperToFactory("+")]
    public class AddFactory : ICalFactory
    {
        public ICalculator GetCalculator()
        {
            return new Add();
        }
    }


    public interface ICalFactory
    {
        ICalculator GetCalculator();
    }

    public interface ICalculator
    {
        double GetResult(double d1, double d2);
    }

    public class Add : ICalculator
    {
        public double GetResult(double d1, double d2)
        {
            return d1 + d2;
        }
    }

    public class Sub : ICalculator
    {
        public double GetResult(double d1, double d2)
        {
            return d1 - d2;
        }
    }

(二) 工厂模式

简单工厂模式面临的问题:在工厂里面用Switch Case决定使用的方法。应当提取出抽象。所以提出了工厂模式

特点:

  1. 工厂模式:给每一种产品都创建生产的工厂。

  2. 产品工厂选择需要的实例工厂。

类图如下:

image-20230402165401447

抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。
具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

大致描述下代码实现:

需要建立每一个产品对应的工厂。先前的加减操作需要由指定的工厂来完成

缺点:如果生产的产品变多,每一种产品都需要新的工厂。那么就会变得冗余。那么我们可以将让每种工厂都生产它品牌下的所有产品。这样尽可能的降低了工厂的数量,所以我们有了抽象工厂模式

(三) 抽象工厂模式

类图模板:

image-20230402170445697

● AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。

● ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。

● AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。

● ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

此时一种工厂生产多种产品,降低了工厂类的需求。

image-20230402175605512

当前需求如下:

image-20230402170235617

实现代码如下:

    public partial class Program
    {
        static void Main(string[] args)
        {
            AdastractFactory adastractFactory = new DellFactory();
            IKeyboard keyboard = adastractFactory.GetKeyboard();
        }
    }

    public interface IKeyboard
    {
        void ShowKeyboardBrand();
    }

    public class DellKeyboard : IKeyboard
    {
        public void ShowKeyboardBrand()
        {
            Console.WriteLine("我是戴尔键盘");
        }
    }

    public class HPKeyboard : IKeyboard
    {
        public void ShowKeyboardBrand()
        {
            Console.WriteLine("我是惠普键盘");
        }
    }

    public interface IMouse
    {
        void ShowIMouseBrand();
    }

    public class DellMouse : IMouse
    {
        public void ShowIMouseBrand()
        {
            Console.WriteLine("我是戴尔鼠标");
        }
    }

    public class HPKeyMouse : IMouse
    {
        public void ShowIMouseBrand()
        {
            Console.WriteLine("我是惠普键盘");
        }
    }

    /// <summary>
    /// 抽象工厂
    /// </summary>
    public interface AdastractFactory
    {
        IKeyboard GetKeyboard();
        IMouse GetMouse();
    }

    public class DellFactory : AdastractFactory
    {
        public IKeyboard GetKeyboard()
        {
            return new DellKeyboard();
        }

        public IMouse GetMouse()
        {
            return new DellMouse();
        }
    }

    public class HPFactory : AdastractFactory
    {
        public IKeyboard GetKeyboard()
        {
            return new HPKeyboard();
        }

        public IMouse GetMouse()
        {
            return new HPKeyMouse();
        }
    }

抽象工厂的其他常见使用场景:

更换数据库:SqlServer变为MySql

    public partial class Program
    {
        static void Main(string[] args)
        {
            User user = new User()
            {
                Name = "123",
                Id = 2
            };

            IFactory factory = new MySqlFactory();
            /// 更换数据库
          ///  IFactory factory = new SqlServerFactory();
            
            IDatabaseUser databaseUser = factory.GetDatabaseUser();
            databaseUser.InsertUser(user);
        }
    }

    public class User
    {
        public string Name { get; set; }

        public int Id { get; set; }
    }


    public interface IDatabaseUser
    {
        void InsertUser(User user);
    }

    public class SqlServerUser: IDatabaseUser
    {
        public void InsertUser(User user)
        {
            Console.WriteLine("SqlServerUser");
        }
    }

    public class MySqlUser : IDatabaseUser
    {
        public void InsertUser(User user)
        {
            Console.WriteLine("MySqlUser");
        }
    }

    public interface IFactory
    {
        IDatabaseUser GetDatabaseUser();
    }

    public class MySqlFactory : IFactory
    {
        public IDatabaseUser GetDatabaseUser()
        {
           return new MySqlUser();
        }
    }

    public class SqlServerFactory : IFactory
    {
        public IDatabaseUser GetDatabaseUser()
        {
            return new MySqlUser();
        }
    }

如果当前的业务需求变更了,需要在原来的基础上做一张部门的表。那么代码变动如下:

    public partial class Program
    {
        static void Main(string[] args)
        {
            User user = new User()
            {
                Name = "123",
                Id = 2
            };

            Department department = new Department()
            {
                Name = "123",
                Id = 2
            };

            IFactory factory = new MySqlFactory();
            /// 更换数据库
          ///  IFactory factory = new SqlServerFactory();
            
            IDatabaseUser databaseUser = factory.GetDatabaseUser();
            databaseUser.InsertUser(user);

            IDatabaseDepartment databaseDepartment = factory.GetDatabaseDepartment();
            databaseDepartment.InsertDepartment(department);
        }
    }

    public class User
    {
        public string Name { get; set; }

        public int Id { get; set; }
    }

    public class Department
    {
        public string Name { get; set; }

        public int Id { get; set; }
    }


    public interface IDatabaseUser
    {
        void InsertUser(User user);
    }

    public interface IDatabaseDepartment
    {
        void InsertDepartment(Department department);
    }


    public class SqlServerUser: IDatabaseUser
    {
        public void InsertUser(User user)
        {
            Console.WriteLine("SqlServerUser");
        }
    }

    public class SqlServerDepartment : IDatabaseDepartment
    {
        public void InsertDepartment(Department department)
        {
            Console.WriteLine("SqlServerDepartment");
        }
    }

    public class MySqlUser : IDatabaseUser
    {

        public void InsertUser(User user)
        {
            Console.WriteLine("MySqlUser");
        }
    }

    public class MySqlDepartment : IDatabaseDepartment
    {
        public void InsertDepartment(Department department)
        {
            Console.WriteLine("MySqlDepartment");
        }
    }



    public interface IFactory
    {
        IDatabaseUser GetDatabaseUser();
        IDatabaseDepartment GetDatabaseDepartment();
    }

    public class MySqlFactory : IFactory
    {
        public IDatabaseUser GetDatabaseUser()
        {
           return new MySqlUser();
        }
        public IDatabaseDepartment GetDatabaseDepartment()
        {
            return new MySqlDepartment();
        }
    }

    public class SqlServerFactory : IFactory
    {
        public IDatabaseUser GetDatabaseUser()
        {
            return new SqlServerUser();
        }
        public IDatabaseDepartment GetDatabaseDepartment()
        {
            return new SqlServerDepartment();
        }
    }

三、原型模式

需求情景:创建重复对象,同时保证了系统的性能

模板类图:

image-20230402183522530

  • 抽象原型类:规定了具体原型对象必须实现的clone()方法
  • 具体原型类:实现了抽象原型类的clone()方法,它是可以被复制的对象
  • 访问类:使用具体原型类中的clone()方法来复制新对象

(一) 浅拷贝

使用场景:只能拷贝值类型。重点是MemberwiseClone()方法

    public partial class Program
    {
        static void Main(string[] args)
        {
            Resume resume = new Resume("张三");
            Resume resume1 = (Resume)resume.Clone();
        }

        public abstract class ResumePrototype
        {
            public string Name { get; set; }
            public ResumePrototype(string name) { this.Name = name; }
            public abstract ResumePrototype Clone();
        }

        public class Resume : ResumePrototype
        {
            public Resume(string name) : base(name) { }

            /// 浅克隆
            /// 值类型 拷贝一份新的
            /// 引用类型 只复制引用
            public override ResumePrototype Clone() { return (ResumePrototype)this.MemberwiseClone(); }
        }
    }

另外一种简单的实现方法,此时不使用抽象原型类:

    public partial class Program
    {
        static void Main(string[] args)
        {
            Resume resume = new Resume() { Id = 1, Name = "Char" };
            Resume resume1 = (Resume)resume.Clone();
        }


        public class Resume : ICloneable
        {
            public int Id { get; set; }
            public string Name { get; set; }

            /// 浅克隆
            /// 值类型 拷贝一份新的
            /// 引用类型 只复制引用
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }
    }

(二)深拷贝

使用场景:既能拷贝值类型也能拷贝引用类型。

WorkExperience是引用类型,需要实现ICloneable接口。

    public partial class Program
    {
        static void Main(string[] args)
        {
            Resume resume = new Resume() { Id = 1, Name = "Char" };
            resume.workExperience.TimeArea = "北京";
            resume.workExperience.Company = "公司";
            Resume resume1 = (Resume)resume.Clone();
        }


        public class WorkExperience : ICloneable
        {
            public string TimeArea { get; set; }
            public string Company { get; set; }
            public object Clone()
            {
                return this.MemberwiseClone();
            }
        }


        public class Resume : ICloneable
        {
            public int Id { get; set; }
            public string Name { get; set; }

            public WorkExperience workExperience;

            public Resume()
            {
                workExperience = new WorkExperience();
            }

            private Resume(WorkExperience workExperience)
            {
                this.workExperience = (WorkExperience)workExperience.Clone();
            }


            /// 深克隆
            /// 值类型 拷贝一份新的
            /// 引用类型 拷贝一份新的
            public object Clone()
            {
                Resume resume = new Resume(this.workExperience);
                resume.Name = this.Name;
                resume.Id = this.Id;
                return resume;
            }
        }
    }

四、建造者设计模式

创建一个复杂的对象构造,让各部分按照一定的顺序进行赋值。

比如:给新房子装修。那么必然按照 改水电-> 抹腻子 -> 刷漆 -> 贴瓷砖 这样的顺序进行

模板类图如下:

image-20230402194445758

  • Product(产品类) :我们具体需要生成的类对象
  • Builder(抽象建造者类):为我们需要生成的类对象,构建不同的模块属性,即:公开构建产品类的属性,隐藏产品类的其他功能
  • ConcreteBuilder(具体建造者类):实现我们要生成的类对象,与产品类是依赖关系
  • Director(导演类):确定构建我们的类对象具体有哪些模块属性,在实际应用中可以不需要这个角色,直接通过client处理

现在以安装电脑为例

实现代码如下:

    public partial class Program
    {
        static void Main(string[] args)
        {
            IBuilderComputer computer = new GoodComputer();
            Directory directory = new Directory();
            directory.BuildComputer(computer);
            Computer goodComputer = computer.GetComputer();
            goodComputer.ShowComputer();
        }

    }

    public interface IBuilderComputer
    {
        void BuildCpu();
        void BuildDisk();
        void BuildMemory();
        void BuildScreen();
        void BuildSystem();
        Computer GetComputer();
    }



    public class Computer
    {
        private List<string> listPart = new List<string>();

        public void AddPart(string part)
        {
            listPart.Add(part);
        }

        public void ShowComputer()
        {
            foreach (var item in listPart)
            {
                Console.WriteLine("正在安装 " + item);
            }
        }
    }

    public class GoodComputer : IBuilderComputer
    {
        private Computer computer = new Computer();
        public void BuildCpu()
        {
            computer.AddPart("Cpu");
        }

        public void BuildDisk()
        {
            computer.AddPart("Disk");
        }

        public void BuildMemory()
        {
            computer.AddPart("Memory");
        }

        public void BuildScreen()
        {
            computer.AddPart("Screen");
        }

        public void BuildSystem()
        {
            computer.AddPart("System");
        }

        public Computer GetComputer()
        {
            return computer;
        }
    }

    public class Directory
    {
        public void BuildComputer(IBuilderComputer builderComputer)
        {
            builderComputer.BuildCpu();
            builderComputer.BuildDisk();
            builderComputer.BuildMemory();
            builderComputer.BuildScreen();
            builderComputer.BuildSystem();
        }
    }

五、适配器模式

image-20230403013824108

使用场景

客户端需要一个target(目标)接口,但是不能直接重用已经存在的adaptee(适配者)类,因为它的接口和target接口不一致,所以需要adapter(适配器)将adaptee转换为target接口。前提是target接口和已存在的适配者adaptee类所做的事情是相同或相似,只是接口不同且都不易修改。如果在设计之初,最好不要考虑这种设计模式。凡事都有例外,就是设计新系统的时候考虑使用第三方组件,因为我们就没必要为了迎合它修改自己的设计风格,可以尝试使用适配器模式。

业务需求:

让苹果手机使用安卓充电线

实现代码:

target是AndroidChargeAdaptee

adapter是PhoneChargeAdapter

    public partial class Program
    {
        static void Main(string[] args)
        {
           IPhoneCharge phoneCharge = new PhoneChargeAdapter();
            phoneCharge.PhoneCharge();
        }
    }

    /// <summary>
    /// 安卓充电线-真正干活的方法
    /// </summary>
    public class AndroidChargeAdaptee
    {
        public void AndroidCharge()
        {
            Console.WriteLine("安卓充电线");
        }
    }

    /// <summary>
    /// 苹果的充电接口
    /// </summary>
    public interface IPhoneCharge
    {
        void PhoneCharge();
    }

    /// <summary>
    /// 转接口
    /// </summary>
    public class PhoneChargeAdapter:IPhoneCharge
    {
        private AndroidChargeAdaptee AndroidChargeAdaptee = new AndroidChargeAdaptee();

        public void PhoneCharge()
        {
            AndroidChargeAdaptee.AndroidCharge();
        }
    }

设计模式(二) 结构型设计模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

一、装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

在这里插入图片描述

角色说明:

抽象构件(Component): 可以是一个接口或者抽象类,充当被装饰类的原始对象,规定了被装饰类的行为。
具体构件(ConcreteComponent): 实现/继承 Component的一个具体对象,即被装饰对象。通过装饰角色为其添加一些职责。
抽象装饰器(Decorator): 实现/继承 Component。通用的 ConcreteComponent的装饰列,其内部必然有一个属性指向 Component,主要是可以通过其子类扩展具体组件的功能。
具体装饰器(ConcreteDecorator): Decorator的具体实现类,并给具体构件对象添加附加的责任,一般为其特有的功能。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

需求:

当下有3种饮料(奶茶、果茶、苏打水),2种小料(珍珠、布丁),计算自由搭配后的价格。

如果我们想要让某种饮料添加多种小料如何实现,如果采用继承的方法,将会导致多个类。

(一杯奶茶,加入两份布丁,一份珍珠)

实现代码如下:

其中YinLiao充当了抽象类,提供了计算花费的方法

Decorator是抽象装饰。

其他多个类实现了具体装饰,通过继承获得了SetComponent的方法,通过重写Cost方法,等同上文中的Operation。

    public partial class Program
    {
        static void Main(string[] args)
        {
            Buding buding1 = new Buding();
            Buding buding2 = new Buding();

            zhenZhu zhenZhu = new zhenZhu();
            MilkTea milkTea = new MilkTea();

            buding1.SetComponent(milkTea);
            buding2.SetComponent(buding1);
            zhenZhu.SetComponent(buding2);
            Console.WriteLine(zhenZhu.Cost().ToString());
        }
    }

    public abstract class YinLiao
    {
        public abstract double Cost();
    }

    public class MilkTea : YinLiao
    {
        public override double Cost()
        {
            Console.WriteLine("奶茶10元一杯");
            return 10;
        }
    }

    public abstract class Decorator : YinLiao
    {
        private YinLiao yinLiao;

        public void SetComponent(YinLiao yinLiao)
        {
            this.yinLiao = yinLiao;
        }

        public override double Cost()
        {
            return this.yinLiao.Cost();
        }
    }

    public class Buding : Decorator
    {
        private static double money = 5;
        public override double Cost()
        {
            Console.WriteLine("布丁5块");
            return base.Cost() + money;
        }
    }

    public class zhenZhu : Decorator
    {
        private static double money = 4;
        public override double Cost()
        {
            Console.WriteLine("珍珠4块");
            return base.Cost() + money;
        }
    }

二、代理设计模式

概念:

代理模式(Proxy Pattern)给某一个对象提供一个代理,并由代理对象控制原对象的引用。代理对象在客户端和目标对象之间起到中介作用 。

代理模式是常用的结构型设计模式之一,当直接访问某些对象存在问题时可以通过一个代理对象来间接访问。

image-20230403024343975

Client通过调用Proxy访问到了RealSubject

小案例:

真实对象RealSubject,通过代理Proxy,访问到ClassFlower。

    public partial class Program
    {
        static void Main(string[] args)
        {
            ClassFlower classFlower = new ClassFlower();
            classFlower.Name = "班花";


            ///创建代理
            ISubject subject = new Proxy(new RealSubject(classFlower));
            subject.GiveSmoking();
            subject.GiveBeer();
            subject.GiveJK();

        }
    }


    public interface ISubject
    {
        void GiveSmoking();
        void GiveBeer();
        void GiveJK();
    }

    public class ClassFlower
    {
        public string Name { get; set; }
    }

    public class RealSubject : ISubject
    {
        private ClassFlower classFlower;

        public RealSubject(ClassFlower classFlower)
        {
            this.classFlower = classFlower;
        }


        public void GiveBeer()
        {
           Console.WriteLine(this.classFlower.Name+"同学,请你喝酒!!!");
        }

        public void GiveJK()
        {
            Console.WriteLine(this.classFlower.Name + "同学,请你穿JK!!!");
        }

        public void GiveSmoking()
        {
            Console.WriteLine(this.classFlower.Name + "同学,请你吸烟!!!");
        }

    }

    public class Proxy : ISubject
    {
        private RealSubject realSubject;
        public Proxy(RealSubject realSubject)
        {
            this.realSubject = realSubject;
        }

        public void GiveBeer()
        {
            this.realSubject.GiveBeer();
        }

        public void GiveJK()
        {
            this.realSubject.GiveJK();
        }

        public void GiveSmoking()
        {
            this.realSubject.GiveSmoking();
        }
    }

几种常见的应用场景:

image-20230403030332648

image-20230403030450154

具体代码案例:

通过代理进行权限上的控制。

Proxy提供检测方法来判断是否具有修改的权限

    public partial class Program
    {
        static void Main(string[] args)
        {
            IOrder order = new ProxyOrder(new RealOrder("笔记本电脑", 100, "张三"));
            order.SetOrderNum(200, "李四");
        }
    }

    public interface IOrder
    {
        string GetProductName();

        void SetProductName(string productName, string user);

        int GetOrderNum();

        void SetOrderNum(int count, string user);

        string GetOrderUser();

        void SetOrderUser(string orderUserName, string user);
    }

    public class RealOrder : IOrder
    {
        public string ProductName { get; set; }

        public int ProductCount { get; set; }

        public string OrderUser { get; set; }

        public RealOrder(string productName, int productCount, string orderUser)
        {
            this.ProductName = productName;
            this.ProductCount = productCount;
            this.OrderUser = orderUser;
        }

        public int GetOrderNum()
        {
            return this.ProductCount;
        }

        public string GetOrderUser()
        {
            return this.OrderUser;
        }

        public string GetProductName()
        {
            return this.ProductName;
        }

        public void SetOrderNum(int count, string user)
        {
            this.ProductCount = count;
        }

        public void SetOrderUser(string orderUserName, string user)
        {
            this.OrderUser = orderUserName;
        }

        public void SetProductName(string productName, string user)
        {
            this.ProductName = productName;
        }
    }

    public class ProxyOrder : IOrder
    {


        private RealOrder realOrder;


        public ProxyOrder(RealOrder realOrder)
        {
            this.realOrder = realOrder;
        }

        public int GetOrderNum()
        {
            return this.realOrder.ProductCount;
        }

        public string GetOrderUser()
        {
            return this.realOrder.OrderUser;
        }

        public string GetProductName()
        {
            return this.realOrder.ProductName;
        }

        public void SetOrderNum(int count, string user)
        {
            if (user!=null && user.Equals(this.realOrder.OrderUser))
            {
                this.realOrder.SetOrderNum(count, user);
            }
            else
            {
                Console.Write("无权限修改");
            }
        }


        public void SetOrderUser(string orderUserName, string user)
        {
            if (user != null && user.Equals(this.realOrder.OrderUser))
            {
                this.realOrder.SetOrderUser(orderUserName, user);
            }
            else
            {
                Console.Write("无权限修改");
            }
        }


        public void SetProductName(string productName, string user)
        {
            if (user != null && user.Equals(this.realOrder.OrderUser))
            {
                this.realOrder.SetProductName(productName, user);
            }
            else
            {
                Console.Write("无权限修改");
            }
        }
    }

三、外观设计模式

外观模式可以理解为,对一个功能系统进行了一定的封装(黑盒子),当然使用也不需要知道它如何实现(透明的),不用关心内部实现只需要使用它所提供的功能即可

代码实现小案例:在办公大厅开证明材料

    public partial class Program
    {
        static void Main(string[] args)
        {
            DaTing daTing = new DaTing();
            daTing.KaiZhengMing();
        }
    }

    public class DaTing
    {
        private Police Police = new Police();
        private Street Street = new Street();
        private Hospital Hospital = new Hospital();

        public void KaiZhengMing()
        {
            Police.GetHuJi();
            Street.GetHuKou();
            Hospital.GetBorn();
        }
    }

    public class Police
    {
        public void GetHuJi()
        {
            Console.WriteLine("开户籍证明");
        }
    }

    public class Street
    {
        public void GetHuKou()
        {
            Console.WriteLine("开户口证明");
        }
    }

    public class Hospital
    {
        public void GetBorn()
        {
            Console.WriteLine("开出生证明");

        }
    }

四、桥接设计模式

面对的问题:

image-20230403172112558

通过大量的基础,产生了大量的子类

image-20230403172908205

抽象和实现分离。不让抽象影响实现。也不让实现影响抽象。避免大量子类的产生

上面问题的解决思路:

image-20230403173615376

代码实现:

    public partial class Program
    {
        static void Main(string[] args)
        {
            Car qyCar = new QYCar();
            qyCar.Move(new Red());
        }
    }

    public interface IColor
    {
        string ShowColor();
    }

    public class Red : IColor
    {
        public string ShowColor()
        {
            return "红色";
        }
    }

    public abstract class Car
    {
        public abstract void Move(IColor color);
    }

    public class QYCar : Car
    {
        public override void Move(IColor color)
        {
            Console.WriteLine(color.ShowColor() + "颜色的汽车在行驶");
        }
    }

五、组合设计模式

组合模式又称:对象树(Object Tree)是一种结构型设计模式,可以使用它将对象组合成树状结构,并且能像使用独立对象一样使用它们。

组合模式(Composite)是针对由多个节点对象(部分)组成的树形结构的对象(整体)而发展出的一种结构型设计模式,它能够使客户端在操作整体对象或者其下的每个节点对象时做出统一的响应,保证树形结构对象使用方法的一致性,使客户端不必关注对象的整体或部分,最终达到对象复杂的层次结构与客户端解耦的目的。

20210619150158

角色说明:

  1. Component 抽象构件角色: 定义参加组合对象的共有方法和属性, 可以定义一些默认的行为或属性
  2. Aggregate 树枝构件: 组合树枝节点和叶子节点形成一个树形结构
  3. Leaf 叶子构件: 其下再没有其的分支, 是遍历的最小单位

使用场景:

如果树形结构系统不使用 组合模式 进行架构,那么按照正常的思维逻辑,对该系统进行职责分析,按上文树形结构图所示,该系统具备两种对象层次类型:树枝节点和叶子节点。那么我们就需要构造两种对应的类型,然后由于树枝节点具备容器功能,因此树枝节点类内部需维护多个集合存储其他对象层次List,List,如果当前系统对象层次更复杂时,那么树枝节点内就又要增加对应的层次集合,这对树枝节点的构建带来了巨大的复杂性,臃肿性以及不可扩展性。同时客户端访问该系统层次时,还需进行层次区分,这样才能使用对应的行为,给客户端的使用也带来了巨大的复杂性。而如果使用组合模式 构建该系统,由于组合模式 抽取了系统各个层次的共性行为,具体层次只需按需实现所需行为即可,这样子系统各个层次就都属于同一种类型,所以树枝节点只需维护一个集合List即可存储系统所有层次内容,并且客户端也无需区分该系统各个层次对象,对内系统架构简洁优雅,对外接口精简易用。

    public partial class Program
    {
        static void Main(string[] args)
        {
            Component company= new DepartComposite("上市公司");
            Component dep1 = new DepartComposite("总裁办");
            Component boss = new Employee("孙权");
            company.Add(dep1);
            dep1.Add(boss);
            company.Display(3);
        }
    }

    public abstract class Component
    {
        public string Name { get; set; }
        public Component(string name)
        {
            this.Name = name;
        }
        public abstract void Add(Component component);
        public abstract void Remove(Component component);
        public abstract void Display(int depth);
    }

    public class DepartComposite : Component
    {
        public DepartComposite(string name) : base(name) { }

        private List<Component> listcomponent = new List<Component>();

        public override void Add(Component component)
        {
            listcomponent.Add(component);
        }

        public override void Remove(Component component)
        {
            listcomponent.Remove(component);
        }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + this.Name);
            foreach (var item in listcomponent)
            {
                item.Display(depth + 4);
            }
        }
    }


    public class Employee : Component
    {
        public Employee(string name) : base(name) { }

        public override void Add(Component component) { }
        public override void Remove(Component component) { }

        public override void Display(int depth)
        {
            Console.WriteLine(new string('-', depth) + this.Name);
        }
    }

六、享元设计模式

享元模式(Flyweight Pattern)又称为轻量级模式,是对象池的一种实现.类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能.提供了减少对象数量从而改善应用所需的对象结构的方式.其宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,从此来降低内存的消耗,属于结构型模式.
享元模式把一个对象的状态分为内部状态外部状态,内部状态即是不变的,外部状态是变化的,然后通过共享不变的部分,达到减少对象数量并节约内存的目的.
享元模式的本质是缓存共享对象,降低内存消耗.

image-20230403214348229

角色:

  1. 抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。
  2. 具体享元(Concrete Flyweight)角色 :它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。
  3. 非享元(Unsharable Flyweight)角色 :并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
  4. 享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

image-20230403221110915

代码案例:小黄车骑行。

    public partial class Program
    {
        static void Main(string[] args)
        {
            BikeFactory bikeFactory = new BikeFactory();

            FlyWeightBike flyWeightBike1 = bikeFactory.GetBike();
            flyWeightBike1.Ride("张三");
            flyWeightBike1.Back("张三");

            FlyWeightBike flyWeightBike2 = bikeFactory.GetBike();
            flyWeightBike2.Ride("李四");

            FlyWeightBike flyWeightBike3 = bikeFactory.GetBike();
            flyWeightBike3.Ride("麻子");
        }
    }

    public abstract class FlyWeightBike
    {
        /// 内部状态 BikeID State 0 锁定 1 骑行中
        /// 外部状态 用户
        /// 骑行 锁定

        public string BikeID { get; set; }
        public int State { get; set; }

        public abstract void Ride(string userName);
        public abstract void Back(string userName);

    }

    public class YellowBike : FlyWeightBike
    {
        public YellowBike(string id)
        {
            this.BikeID = id;
        }

        public override void Back(string userName)
        {
            this.State = 0;
            Console.WriteLine(userName + " " + "规还了自信车" + this.BikeID);
        }

        public override void Ride(string userName)
        {
            this.State = 1;
            Console.WriteLine(userName + " " + "正在骑行自信车" + this.BikeID);
        }
    }

    public class BikeFactory
    {
        List<FlyWeightBike> bikePool = new List<FlyWeightBike>();
        public BikeFactory()
        {
            for (int i = 0; i < 3; i++)
            {
                bikePool.Add(new YellowBike(i.ToString()));
            }
        }

        public FlyWeightBike GetBike()
        {
            for (int i = 0; i < bikePool.Count; i++)
            {
                if (bikePool[i].State == 0)
                {
                    return bikePool[i];
                }
            }
            return null;
        }
    }
posted @ 2023-04-05 03:37  聆听微风  阅读(75)  评论(0编辑  收藏  举报