常见的设计模式

发布于:2023-01-01 ⋅ 阅读:(286) ⋅ 点赞:(0)

工厂模式

这个模式有三个对象:工厂、用户、产品;这么说可能还有点抽象,说具体点,就是当我们在代码中需要生成一个类实例时,不直接去拿到这个类名,然后new;而是通过一个工厂类(例如EntityFactory),给该工厂类传要创建的类名的字符串,获取到最后生成的类实例;这样做的好处是,将对象的构造和使用隔离,使之模块化,工厂化。


C#示例代码如下所示:

//设计模式----工厂模式示例代码
using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    abstract class Animal
    {
        public string name;
        public Animal(string _name) { name = _name; }

        abstract public void Func() ;
    }

    class Dog: Animal
    {
        public Dog(string _name) :base(_name) { name = _name; }
        override public void Func()
        {
            Console.WriteLine($"Dog, name is {name}");
        }
    }

    class Monkey:Animal
    {
        public Monkey(string _name) : base(_name) { name = _name; }
        override public void Func()
        {
            Console.WriteLine($"Monkey, name is {name}");
        }
    }

    class Duck:Animal
    {
        public Duck(string _name) : base(_name) { name = _name; }
        override public void Func()
        {
            Console.WriteLine($"Duck, name is {name}");
        }
    }

    class AnimalFactory // 只需要传字符串到工厂,就能生成对应的类实例,然后利用多态,调用一样的接口,对应不一样的实现
    {
        private static AnimalFactory Instance;
        public static AnimalFactory GetInstance()
        {
            if(Instance == null)
            {
                Instance = new AnimalFactory();
            }
            return Instance;
        }

      public dynamic CreateAnimal(string class_name, string animal_name)
        {
            Type type = Type.GetType("ConsoleApp1." + class_name); // 利用反射获取到对应类名的Type
            dynamic obj = Activator.CreateInstance(type, new object[] { animal_name}); //生成对应的实例
            return obj;
        }
    }

    class Program
    {
        
        public static void  Main()
        {
            Dictionary<string, string> nameDic = new Dictionary<string, string> 
            { 
                { "Dog", "xiaowang" },
                { "Duck", "xiaoli" },
                { "Monkey", "xiaozhang" },
            };

            foreach(var namePair in nameDic)
            {
                Animal animal = (Animal)AnimalFactory.GetInstance().CreateAnimal(namePair.Key, namePair.Value);
                animal?.Func();
            }
        } 
}
}

单例模式

在内存中只存在一个实例对象,通常的构成是:私有构造函数静态公共获取函数私有静态自身成员;创建单例的方式有懒汉模式饿汉模式静态内部类实现等。

这是C++实现

#include<iostream>
#include<string>
using namespace std;

class Singleton1 // 懒汉模式
{
private:
	static Singleton1* _instance;
	Singleton1() { cout << "Singleton1 created !!!!"; }
public:
	static Singleton1* GetInstance()
	{
		if (_instance == NULL)
		{
			_instance = new Singleton1();
		}
		return _instance;
	}
};
Singleton1* Singleton1::_instance; 
//--------------------------------------------------------------------------
class Singleton2 // 饿汉模式
{
private:
	static Singleton2* _instance;
	Singleton2() {cout<<"Singleton2 created !!!!"; };

public:
	static Singleton2* GetInstance()
	{
		return _instance;
	}
};

Singleton2* Singleton2::_instance = new Singleton2();

//------------------------------------------------------------------------------------

class Singleton3 // 局部静态变量实现,还有一种是加锁模式,比较麻烦且耗,需要的百度下就行
{
private:
	Singleton3() { cout << "Singleton3 created !!!!"; };
public:
	static Singleton3& GetInstance()
	{
		static Singleton3  instance;
		return instance;
	}
};

这是c#实现

// 设计模式————单例模式(懒汉、饿汉、静态内部类实现)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ConsoleApp1
{

    public class Singleton1 // 懒汉模式, 多线程不安全,会创建多个
    {
        private static Singleton1 _Singleton1 = null;
        private Singleton1()
        {
            Console.WriteLine("Singleton1被构造");
        }
        public static Singleton1 GetInstance()
        {
            if (_Singleton1 == null)
            {
                _Singleton1 = new Singleton1();
            }
            return _Singleton1;
        }
    }

    public class Singleton2  // 饿汉模式,这里多线程运行状态下是线程安全的
    {
        private Singleton2() { Console.WriteLine("Singleton2被构造"); }
        private static Singleton2 Instance = new Singleton2();
        public static Singleton2 GetInstance() 
        {
            return Instance;
        }
    }

    public class Singleton3 // 内部静态类实现,多线程安全
    {
        private Singleton3() { Console.WriteLine("Singleton3被构造"); }
        private static class InnerClass
        {
            internal static Singleton3 instance = new Singleton3();
            static InnerClass() {}  //静态构造函数
        }
        public static Singleton3 GetInstance()
        {
            return InnerClass.instance;
        }
    }

    public class Singleton4 //静态构造函数, 构造线程安全,保证内存只有一个这个实例对象
    {
        private static Singleton4 Instance;
        private Singleton4() { Console.WriteLine("Singleton4被构造"); }
        static Singleton4()
        {
            Instance = new Singleton4();
        }
        public static Singleton4 GetInstance()
        {
            return Instance;
        }
    }

    public class Singleton5 // 惰性构造,构造线程安全
    {
        private static readonly Singleton5 instance = new Singleton5();
        private Singleton5() { Console.WriteLine("Singleton5被构造"); }
        static Singleton5() {}  // 静态构造,保证只调用一次,并且在调用一个静态方法或者属性时,初始化这个类
        public static Singleton5 Instance
        {
            get
            {
                return instance;
            }
        }
    }

    class Program
    {
        public static void F1()
        {
            for (int i = 0; i < 10; ++i)
            {
                var a = Singleton2.GetInstance();
            }
        }
        public static void Main()
        {
            // 验证多线程状态下的线程安全
            Thread thread1 = new Thread(new ThreadStart(F1));
            thread1.Start();

            Thread thread2 = new Thread(new ThreadStart(F1));
            thread2.Start();
        }
    }
}

这是网上有另外一个大佬,关于c#单例的讲解

观察者模式

当一个事件发生时,需要去通知其他订阅者;例如游戏里面常见的领完奖励之后刷新UI界面等等。通过注册的方式,实现事件的统一下触发以及代码的隔离。

c#代码示例

//设计模式----观察者/订阅者模式
using System;

namespace ConsoleApp1
{
    public class Subscriber  // 发布者
    {
        public event Action mineActions;
        public Subscriber()
        {
        }

        public void registEvent(Action action)
        {

            mineActions += action;
        }

        public void unRegisterEvent(Action action)
        {
            mineActions -= action;
        }

        public void publishEvent()
        {
            mineActions?.Invoke();
        }
    }

    public abstract class ObserverBase
    {
        public string name;
        public ObserverBase(string _name)
        {
            name = _name;
        }
        public abstract void F1();

    }

    public class ObserverA: ObserverBase  // 订阅者A
    {
        public ObserverA(string _name):base(_name)
        {
            name = _name;
        }
        public override void F1()
        {
            Console.WriteLine($"this is {name} print !!!!!!!");
        }
    }

    public class ObserverB: ObserverBase // 订阅者B
    {
        public ObserverB(string _name) : base(_name)
        {
            name = _name;
        }
        public override void F1()
        {
            Console.WriteLine($"this is {name} print !!!!!!!");
        }
    }

    public class ObserverC : ObserverBase  // 订阅者C
    {
        public ObserverC(string _name) : base(_name)
        {
            name = _name;
        }
        public override void F1()
        {
            Console.WriteLine($"this is {name} print !!!!!!!");
        }
    }


    class Program
    {

        public static void Main()
        {
            Subscriber subscriber = new Subscriber();
            ObserverA observerA = new ObserverA("ObserverA");
            ObserverB observerB = new ObserverB("ObserverB");
            ObserverC observerC = new ObserverC("ObserverC");

            //订阅
            subscriber.registEvent(observerA.F1);
            subscriber.registEvent(observerB.F1);
            subscriber.registEvent(observerC.F1);

            //发布事件
            subscriber.publishEvent();

            //取消订阅
            subscriber.unRegisterEvent(observerA.F1);
            subscriber.unRegisterEvent(observerB.F1);
            subscriber.unRegisterEvent(observerC.F1);
        }
    }
}

策略模式

意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

同一种方式有多重实现方法,例如

  • 登录到某个网站,可以用手机号登录、扫码登录、账号密码登录等,都是为了登录到同一个账号。
  • 去沃尔玛买购物,结账的时候可以使用现金,支付宝、微信以及购物卡,都是为了结账。
  • 高德地图导航时,可以选择步行、骑车、开车等不同方式,给出的路线不一样。

代码示例

using System;
using System.Collections.Generic;
using System.Text;

namespace Strategy
{

    public abstract class StrategyBase
    {
        public abstract int F(int a, int b);
    }

    public class StrategyA: StrategyBase // 策略A
    {
        public override int F(int a, int b)
        {
            return a + b;
        }
    }

    public class StrategyB : StrategyBase // 策略B
    {
        public override int F(int a, int b)
        {
            return a - b;
        }
    }

    public class StrategyC : StrategyBase // 策略C
    {
        public override int F(int a, int b)
        {
            return a * b;
        }
    }

    public class Context // 代表上下文
    {
        StrategyBase strategyBase;
        public Context(StrategyBase _strategy)
        {
            strategyBase = _strategy;
        }

        public int F(int a, int b)
        {
            return strategyBase.F(a, b);
        }

    }

    public class Program
    {
        public static void Main()
        {
            Context a = new Context(new StrategyA()); // 使用策略A
            Context b = new Context(new StrategyB()); // 使用策略B
            Context c = new Context(new StrategyC()); // 使用策略C
            //调用的时候使用统一接口 F
            Console.WriteLine($"a.F(1,2) = {a.F(1, 2)}, b.F(1, 2) = {b.F(1, 2)}, c.F(1, 2) = {c.F(1, 2)}");
        }
    }
}

在上述的示例代码中,对于同样的使用环境(Context类),当使用不一样的策略是,可以有不一样的实现。


代理模式

在真实的某个对象上再包一层代码,可以很方便的扩展其功能;例如游戏中的相机,我们可以在原生相机的基础上包装一层,然后可以在这一层代理里面加一些保护、实现一些原生接口函数的组合功能等。

动机:限制对目标对象的直接访问,降低耦合度;还可以实现一些真实对象没有的接口或者一些现有功能的组合。

示例代码:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApp1
{
    class Subject // 真实对象
    {
        public void fun1()
        {

        }

        public void fun2()
        {

        }

        public void fun3()
        {

        }
    }

    class SubjectProxy  //代理对象,实现和真实对象一样的接口,可以限制对目标对象的直接访问,降低耦合度。
    {
        Subject subject;
        public SubjectProxy(Subject _subject)
        {
            subject = _subject;
        }

        public void fun1() // 这里做封装,可以打log,加保护
        {
            subject.fun1();
        }

        public void fun2()
        {
            subject.fun2();
        }

        public void fun3()
        {
            subject.fun3();
        }
    }

    public class Proxy
    {
        public static void Main()
        {
            SubjectProxy subjectProxy = new SubjectProxy(new Subject());
            subjectProxy.fun1();
            subjectProxy.fun2();
            subjectProxy.fun3();
        }
    }
}


装饰模式

可以对原来的函数或者类进行扩展;对于类的装饰,可以实现组件式的代码结构,使得各个功能可以和方便的添加与删除,并且代码的逻辑也会很清晰;实现的功能是以组件的形式实现与继承相似的效果。

解决的问题: 一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApp1
{

    public abstract class Shape // 抽象基类
    {
        public abstract void Print();

    }

    public class Circle: Shape // 圆形
    {
        public override void Print()
        {
            Console.WriteLine("This is Circle Draw !!");

        }
    }

    public class Triangle : Shape // 三角形
    {
        public override void Print()
        {
            Console.WriteLine("This is Triangle Draw !!");

        }
    }

    public class Decorator: Shape  // 装饰类
    {
        public Shape shape;

        public Decorator(Shape _shape)
        {
            shape = _shape;
        }
        public override void Print()
        {
            Console.WriteLine("This is Triangle Draw !!");

        }
    }

    public class ColorShapeDecorator : Decorator  // 装饰类型1
    {
        public ColorShapeDecorator(Shape _Shape) : base(_Shape)
        {

        }

        public override void Print()
        {
            shape.Print();
        }

        public void Color()  //相当于在传进来Shape的基础上,增加了Color接口
        {
            // DoSomething
            Console.WriteLine("This is Color function !!");
        }
    }

    public class GeometryShapeDecorator : Decorator  // 装饰类型2
    {
        public GeometryShapeDecorator(Shape _Shape) : base(_Shape)
        {

        }

        public override void Print()
        {
            shape.Print();
        }

        public void GetArea()  //相当于在传进来Shape的基础上,增加了GetArea接口
        {
            // DoSomething
            Console.WriteLine("this is GetArea function !!");
        }

        public void GetGirth()  //相当于在传进来Shape的基础上,增加了GetGirth接口
        {
            // DoSomething
            Console.WriteLine("this is GetGirth function !!");
        }
    }

    class DecoratorTest
    {
        public static void Main()
        {
            Circle circle = new Circle();
            circle.Print();
            Console.WriteLine("--------------------------------------------");
            Triangle triangle = new Triangle();
            triangle.Print();

            Console.WriteLine("--------------------------------------------");
            ColorShapeDecorator ShapeDecoratorShape1 = new ColorShapeDecorator(circle);
            ShapeDecoratorShape1.Print();
            ShapeDecoratorShape1.Color(); // 在circle的基础上扩展了Color函数

            Console.WriteLine("--------------------------------------------");
            GeometryShapeDecorator ShapeDecoratorShape2 = new GeometryShapeDecorator(triangle);
            ShapeDecoratorShape2.Print();
            ShapeDecoratorShape2.GetArea(); // 在triangle的基础上扩展了GetArea、GetGirth等函数
            Console.WriteLine("--------------------------------------------");
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到