• 代理模式 工厂模式 原型模式


    没有代理的代码

    情景:小王想送小李洋娃娃和鲜花,但是不好意思直接送,所以让小陈来帮忙。

    //女孩类
    class SchoolGirl {
    private:
    	string name;
    public:
    	void setName(string name)
    	{
    		this->name = name;
    	}
    	
    	string getName()const {
    		return this->name;
    	}
    };
    
    //小王
    class Pursuit {
    public:
    	Pursuit(SchoolGirl *mm)
    	{
    		this->mm = mm;
    	}
    
    	void GiveDolls()
    	{
    		cout << mm->getName() << "送你洋娃娃" << endl;
    	}
    
    	void GiveFlowers()
    	{
    		cout << mm->getName() << "送你鲜花" << endl;
    	}
    private:
    	SchoolGirl *mm;
    };
    
    //main
    int main()
    {
    	SchoolGirl* L = new SchoolGirl();
    	L->setName("小李");
    	Pursuit* ZZ = new Pursuit(L);
    	ZZ->GiveDolls();
    	ZZ->GiveFlowers();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    这样写就相当于小王自己直接送给小李,并没有使用带代理。

    //定义接口
    __interface GiveFift
    {
    	void GiveDolls();
    	void GiveFlowers();
    };
    
    //代理类
    class Proxy :public GiveFift{
    private:
    	Pursuit *gg;
    public:
    	Proxy(SchoolGirl* mm)
    	{
    		gg = new Pursuit(mm);
    	}
    
    	void GiveDolls()
    	{
    		gg->GiveDolls();
    	}
    
    	void GiveFlowers()
    	{
    		gg->GiveFlowers();
    	}
    };
    
    使用
    	SchoolGirl* L = new SchoolGirl();
    	L->setName("小小");
    
    	Proxy* XC = new Proxy(L);
    	
    	XC->GiveDolls();
    	XC->GiveFlowers();
    	return 0;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    代理模式:为其他对象提供一种代理以控制对这个对象的访问

    另一种写法

    //接口类
    class Subject
    {
    public:
    	virtual void Request() = 0;
    };
    
    //真实请求
    class RealSubject : Subject
    {
    public:
    	void Request() 
    	{
    		cout << "真实的请求" << endl;
    	}
    };
    
    //第三方代理
    class Proxy_ :Subject {
    public:
    	void Request()
    	{
    		if(realSubject == nullptr)
    		{
    			realSubject = new RealSubject();
    		}
    		realSubject->Request();
    	}
    private:
    	RealSubject *realSubject;
    };
    
    //调用
    	Proxy_* proxy = new Proxy_();
    	proxy->Request();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    代理模式一般用在什么场合呢?

    1. 远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
    2. 虚拟代理。根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。比如一个很大的HTML网页,里面可能有很多的文字和图片,但你还是可以很快的打开它,此时你可以看到所有的文字,但是图片却是一张一张的下载后才能看到。那些未打开的图片框,就是通过虚拟代理来替代了真实的图片,此时代理存储了真实图片的路径和尺寸。
    3. 安全代理。用来控制真实对象访问时的权限。用于对象应该有不同的访问权限的时候。
    4. 智能指引,当调用真实的对象时,代理处理另外一些事。比如计算真实对象的引用次数,这样当该对象没有引用时,可以自动释放它,或当第一次引用一个持久对象时,将它装入内存,或在访问一个实际对象前,检查是否已经锁定它,以确保其他对象不能改变它。
      代理就是真实对象的代表

    计算器的工厂模式

    //操作对象类
    class Operation {
    public:
    	void setNumberA(double val){numberA = val;}
    	void setNumberB(double val){numberB = val;}
    	double getNumberA() const{return numberA;}
    	double getNumberB() const{return numberB;}
    
    	virtual double GetResult() = 0;
    private:
    	double numberA, numberB;
    };
    
    //工厂类
    class IFactory
    {
    public:
    	virtual Operation *CreateOperation() = 0;
    };
    
    //加法类
    class OperationAdd :public Operation {
    public:
    	double GetResult()
    	{
    		double result = 0;
    		result = getNumberA() + getNumberB();
    		return result;
    	}
    };
    
    //加法类工厂
    class AddFactory :public IFactory {
    public:
    	Operation *CreateOperation(){
    		return new OperationAdd();
    	}
    };
    
    //main
        IFactory* operFactory = new AddFactory();
    	Operation *oper = operFactory->CreateOperation();
    	oper->setNumberA(1);
    	oper->setNumberB(2);
    	double result = oper->GetResult();
    	cout << "result " << result << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在简单工厂里,如果需要加一个减法功能,则先加一个减法类,然后去更改工厂的方法,在“Case”语句里判断,但是现在用了工厂方法,加减法类没有问题,再加相关的工厂类,这也没有问题,但是还要去改客户端,这不等于不但没有简化难度,反而增加了很多类和方法,把复杂性增加了。
    简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖
    就像计算器,让客户端不用管改用哪个类的实例,只需要把“+”给工厂,工厂自动就给出了相应的实例,客户端只要去做运算就可以了,不同的实例会实现不同的运算。但问题就在这里,如果要加一个减法的功能,我们是一定需要给运算工厂类的方法里加“Case”分支条件,修改原有的类?这就等于说,我们不但对扩展开放了,对修改也开放了,这就违背了开放-封闭原则。
    工厂方法模式定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
    既然工厂类与分支耦合,那么就对它下手,根据依赖倒转原则,把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,于是,我们要增加其他运算规则,就不需要更改原有的工厂类,只需要增加此功能的运算类和对应的工厂类就可以了。
    工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,你想要加功能,本来是改工厂类的, 而现在是修改客户端。

    原型模式

    //简历类
    class Resume {
    private:
    	string name;
    	string sex;
    	string age;
    public:
    	Resume(string name)
    	{
    		this->name = name;
    	}
    
    	void SetPersonalInfo(string sex, string age)
    	{
    		this->sex = sex;
    		this->age = age;
    	}
    
    	void Display()
    	{
    		cout << "name " << name << " age " << age << " sex " << sex << endl;
    	}
    };
    
    //main
    	Resume* a = new Resume("小王");
    	a->SetPersonalInfo("男", "25");
    	a->Display();
    
    	Resume* b = new Resume("小王");
    	b->SetPersonalInfo("男", "25");
    	b->Display();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    如果客户端这样编写,则多少份简历就要编写多少份,要是一个字错了,那就要改很多遍。所以,可以写成以下形式

    	Resume* a = new Resume("小王");
    	a->SetPersonalInfo("男", "25");
    	a->Display();
    	Resume* b = a;
    	b->Display();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    原型模式(Prototype)指定创建对象的种类,并且通过拷贝这些原型创建新的对象,就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节

    //原型类
    class Prototype {
    private:
    	string id;
    
    public:
    	Prototype(string id)
    	{
    		this->id = id;
    	}
    
    	string Id()
    	{
    		return id;
    	}
    
    	void _SetID(string id)
    	{
    		this->id = id;
    	}
    
    	virtual Prototype *Clone() = 0;
    };
    
    class ConcreatePrototype :public Prototype
    {
    public:
    	ConcreatePrototype(string id):Prototype(id){}
    	virtual ConcreatePrototype *Clone()
    	{
    		return new ConcreatePrototype(*this);
    	}
    
    	void SetID(string id)
    	{
    		this->_SetID(id);
    	}
    };
    
    //main
    	ConcreatePrototype *p1 = new ConcreatePrototype("I");
    	ConcreatePrototype *c1 = p1->Clone();
    	p1->SetID("p1");
    	c1->SetID("c1");
    
    	cout << "p1 addr " << &p1 << " c1 addr " << &c1 << endl;
    	cout << p1->Id() << endl;
    	cout << c1->Id() << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    这样,如果需要更改其中一个对象,只需要对这个对象做一定的修改就行了,不会影响到其他的对象,相同的部分就不用再重复了。而且性能也会大大的提高,毕竟,每new一次,都需要执行一次构造函数,如果构造函数的执行时间很长,那么多次的执行这个初始化操作实在是太低效了。一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这既隐藏了对象创建的细节,又对性能是大大的提高。等于是不用重新初始化对象,而是动态地获得对象运行时的状态

  • 相关阅读:
    Solidus Labs欢迎香港前金融创新主管赵嘉丽担任战略顾问
    江西省职业院校技能大赛中职组网络安全竞赛之Linux操作系统渗透测试
    操作系统体系结构和OS
    苹果电脑要安装杀毒软件吗?mac用什么杀毒软件好?
    python3 win环境部署
    Springboot发送邮件
    快解析结合友加畅捷通t1飞跃版
    Spring Boot (三)
    C语言实验五 循环结构程序设计(二)
    RibbitMQ学习笔记之死信队列
  • 原文地址:https://blog.csdn.net/a12345d132/article/details/126396465