【设计模式学习笔记1】原型法

4 篇文章 0 订阅

设计模式不是代码的复用,而是经验的复用。要经过分析之后确定哪个是抽象,那个是具体。

依赖关系的倒置:

抽象不应该依赖于细节,实现细节应该依赖于抽象。

反之软件易碎。



人是抽象A,陶瓷水杯可以是一个实现细节b。即人拿一个水杯。但是陶瓷水杯是一个易变类,因此转化成下面的图。把它的实现分解成两种,一个抽象,一个具体。即先分解成一个水杯,水杯是抽象部分。再分解的一部分是陶瓷水杯,具体实现部分。而人只需要依赖于抽象的水杯,这样系统中可以任意的更换水杯的类型。

依赖倒置的原则是抽象变化慢,细节变化快。



转化为



人是抽象A

面向对象三大特性:

继承、多态、封装。可以实现更好地依赖关系

原型设计模式(Prototype

动机:

在软件系统中,经常面临某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着巨大的变化,但是他们却拥有比较稳定一致的借口。

客户程序 A使用BA就是B的客户程序。

如何将客户程序隔离出这些易变对象,从而使得 依赖这些易变对象的客户程序 不随着需求的改变儿改变?

结构:

ClintGameSystem,PrototypeNormalActorConcreatePrototype1就是normalActor1

意图:

使用原型实例(如normalActor)来创建对象,然后通过拷贝来创建新的对象。

例子:

Public class GameSystem
{
public static void Run(){
NormalActor normalActor1 = new NormalActorA();
NormalActor normalActor2 = new NormalActorB();
FlyActor flyActor = new FlyActor();
}
}


这是正常的方法。

声明类型和实现类型是同一个类型,这就是抽象依赖具体的表现,应该摒弃。

public abstract class NormalActor{
}
public abstract class FlyActor{
}
public abstract class WaterActor{
}
public class NormalActorA:NormalActor{
public override NormalActor Clone(){
return (NormalActorA)this.MemberwiseClone();
//利用了.NET的克隆方法,按照成员浅拷贝。所有值类型都没有问题,但是如果出现如数组这种类型,
//则拷贝过去的只是数组的地址
//深克隆就是没有共享部分,相互不影响
}
}
//NormalActorB等等也是如此,这样细节B依赖于抽象B
Public class GameSystem
{
public static void Run(NormalActor normalActor,
FlyActor flyActor,
WaterActor waterActor)
{
NormalActor normalActor1 = normalActor.Clone();
NormalActor normalActor2 = normalActor.CloneA();
FlyActor flyActor1 = flyActor.Clone();
WaterActor waterActor1 = waterActor.Clone();
}
}
这样GameSystem就不用依赖于各种Actor的子类。现在就是抽象A依赖于抽象B
class App{
public static void Main(){
GameSystem gameSystem = new GameSystem;
gameSystem.Run(new NormalActorA(),
new FlyActorB(),
new WaterAcotorC());
//程序主逻辑不变,参数可以变化。
}
}


要点:

Prototype模式要求这些“易变类”拥有“稳定的借口”

原型法模式对于如何创建易变类的实体对象采用原型克隆的方法来做,它使得我们可以非常灵活的创建 拥有某些稳定借口 的新对象,所需工作紧紧是注册一个新类的对象。然后在人需要的地方不断地克隆。


创建型模式的讨论:

Singleton模式解决的是实体对象个数的问题。出了singleton之外,其他创建型模式解决的都是new所带来的耦合关系。

工厂(一个对象)、抽象工厂(对个关联对象)和Builder(利用复杂的算法创建组合对象)都需要一个额外的工厂类来负责实例化“易变对象”,儿Prototype则是通过原型(一个特殊的工厂类)来克隆“易变对象”。

如果遇到“易变类”,起初的设计从Factory Method开始,当遇到更多复杂的变化时,再刻意考虑重构为其他三种工厂模式(Abstract Factory,Builder,Prototype)。

Prototype最好是方便克隆的,可以通过加序列化的方式来方便克隆。

下面再以老师的代码样子做解释:

#include <iostream>
using namespace std;
class Prototype//如同NormalActor
{
 public:
  int abc;
  virtual void func(){cout<<"prototype func";}
  virtual Prototype* Clone()
  {
      return new Prototype(*this);
  }//原型的克隆方法,虚函数,目的为了子类的重写
  Prototype(int n){abc=n;}
  Prototype(const Prototype& p)
  {
     abc=p.abc;
  }
};
class ConcretePrototype:public Prototype//如NormalActor1
{
 public:
   int conabc;
   void func(){cout<<"ConcretePrototype func conabc="<<conabc;}
   Prototype* Clone()
   {
      return new ConcretePrototype(*this);
   }
   ConcretePrototype(int other):Prototype(other)
   {     
         conabc=other/2;
   }
   ConcretePrototype(const ConcretePrototype& other):Prototype(other)
   {    
      conabc=other.conabc ;
   }
};
main()
{
 //Prototype* prototype=new Prototype(9765);
 Prototype* prototype=new ConcretePrototype(10);
 Prototype* p;
 p=prototype->Clone();//再创建实例的时候不需要new只需要赋值已有实例即可。
   //p=new Prototype(*prototype);
 p->func();
 cout<<p->abc;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值