存档在 ‘设计模式’ 分类

SQL的主键和外键约束

2015年5月28日

一、SQL的主键和外键的作用

外键取值规则:空值或参照的主键值。

(1)插入非空值时,如果主键表中没有这个值,则不能插入。
(2)更新时,不能改为主键表中没有的值。
(3)删除主键表记录时,你可以在建外键时选定外键记录一起级联删除还是拒绝删除。
(4)更新主键记录时,同样有级联更新和拒绝执行的选择。

简而言之,SQL的主键和外键就是起约束作用。

» 阅读更多: SQL的主键和外键约束

Rose出现 “relation from A to B would cause an Invalid circular***”解决方法

2014年2月20日

UML建模工具Rose出现 “relation from A to B would cause an Invalidcircular inheritance /realization combination解决方法。

出现原因

出现这种情况往往是在绘图之前,两个类A和B之间就建立了关系。
在绘图过程中,由于操作失误,继承关系发生错误,正确继承关系为Man继承自Person。但我在删除该关系时,采用了按“delete”或者右键“edit”—>”delete”方法。此时person和Man之间的关系并没有真正的删除。当我在重新建起两者之间关系时,会出现以下错误。

解决方法

(1)恢复原来的person与Man 之间的错误关系:
具体步骤是在brower中选择继承关系,连接Person与Man
(2)在错误的关系上,右键editàdelete from model 或者(Ctrl+D)删除。
(3)重新建立Person与Man之间的正确关系:

归纳与总结

在rose中采用采用了按“delete”或者右键“edit”—>”delete”方法并不能真正地删除两类之间的关系,需要采用 ctrl+D组合键方式删除。

关联、组合、聚合、依赖比较

2014年2月18日

类之间的关系
1. 种类: Generalization(泛化),Dependency(依赖关系)、Association(关联关系)、Aggregation(聚合关系)、Composition(合成关系)。

2. 其中Aggregation(聚合关系)、Composition(合成关系)属于Association(关联关系),是特殊的Association关联关系。

3. Generalization(泛化)表现为继承或实现关系(is a)。具体形式为类与类之间的继承关系,接口与接口之间的继承关系,类对接口的实现关系。
1
» 阅读更多: 关联、组合、聚合、依赖比较

UML类图的5种关系

2013年5月4日

这篇文章是转载别人的,感觉写的比较清晰,所以搬了过来。

主要有:关联关系、泛化、依赖、聚合和组合。可以细分为

1、单向关联

2、双向关联

3、自身关联

4、多维关联(N-ary Association)

5、泛化(Generalization)

6、依赖(Dependency)

7、聚合(Aggregation)

8、组合(Composite)

» 阅读更多: UML类图的5种关系

简单工厂,工厂方法和抽象工厂三种设计模式的区别与C++实现

2013年3月31日

1.简单工厂:简单工厂无需定义抽象工厂类,一般是依靠case,或者if..else..加以判断来产生不同的产品对象。总的来说为“将产品抽象出来,工厂类无需抽象,全部产品都由这个工厂类产生”;

2.工厂方法:针对每一个产品都定义一个派生工厂类,派生工厂类中有一个方法(函数)来产生产品对象,所以叫做工厂方法。总的来说为“将产品抽象出来,将工厂抽象出来,一个工厂子类来产生一个产品子类对象”;

3.抽象工厂:抽象程度更高,工厂方法将所有产品都抽象成几个基类。 如果有多个基类的话,则针对这一系列商品就需要抽象工厂。抽象工厂把几种产品抽象共同的东西,把相互依赖的对象抽象出来,只要实现这些接口就可以得到不同的产品.
» 阅读更多: 简单工厂,工厂方法和抽象工厂三种设计模式的区别与C++实现

C++实现中介者设计模式在项目中应用

2013年3月24日

项目中存在机器人类,路径规划类,串口类,分别为:Robot ,RobotPathPlan,RobotSerial
robot.h

#ifndef ROBOT_H_
#define ROBOT_H_
class Mediator;
class Robot
{
public:
	Robot(Mediator *);
	void sendMsg(int n);
	void setPoint(int p);
	int getSonarByIndex(int i);
	void processData();
private:
	Mediator *mediator;
};
#endif

robot.cpp

#include "robot.h"
#include "mediator.h"
#include <iostream>
using namespace std;

Robot::Robot(Mediator* media) : mediator(media){}
void Robot::sendMsg(int n)
{
	mediator->sendMsg(n);
}
void Robot::setPoint(int p)
{
	mediator->setPoint(p);
}
int Robot::getSonarByIndex(int i)
{
	cout<<"获取第"<<i<<"个超声波"<<endl;
	return 1;
}
void Robot::processData()
{
	cout<<"机器人类开始处理数据"<<endl;
}

pathplan.h

#ifndef PATHPLAN_H_
#define PATHPLAN_H_
class Mediator;
class PathPlan
{
public:
	PathPlan(Mediator* media);
	int getSonarByIndex(int i);
	void setPoint(int p);
private:
	Mediator *mediator;
};

#endif

pathplan.cpp

#include "pathplan.h"
#include "mediator.h"
#include <iostream>
using namespace std;

PathPlan::PathPlan(Mediator* media) : mediator(media){}
int PathPlan::getSonarByIndex(int i) 
{
	return mediator->getSonarByIndex(i);
}

void PathPlan::setPoint(int p)
{
	cout<<"设置机器人目标点为"<<p<<endl;
}

robotserial.h

#ifndef ROBOTSERIAL_H_
#define ROBOTSERIAL_H_
class Mediator;

class RobotSerial
{
public:
	RobotSerial(Mediator* media);
	void sendMsg(int n);
	void processData();

private:
	Mediator *mediator;
};
#endif 

robotserial.cpp

#include "robotserial.h"
#include "mediator.h"
#include <iostream>
using namespace std;

RobotSerial::RobotSerial(Mediator* media) : mediator(media){}

void RobotSerial::sendMsg(int n)
{
	cout<<"发送命令"<<n<<endl;
}
void RobotSerial::processData()
{
	mediator->processData();
}

mediator.h

#ifndef MEDIATOR_H_
#define MEDIATOR_H_
class Robot;
class RobotSerial;
class PathPlan;

class Mediator
{
public:
	void registRobot(Robot *tRobot);
	void registRobotSerial(RobotSerial* tRobotSerial);
	void registPathPlan(PathPlan *tPathplan);

	void setPoint(int p);
	int getSonarByIndex(int i);
	void sendMsg(int n);
	void processData();
private:
	Robot *robot;
	RobotSerial *robotSerial;
	PathPlan *pathPlan;
};
#endif 

mediator.cpp

#include "mediator.h"
#include "robot.h"
#include "robotserial.h"
#include "pathplan.h"

void Mediator::registRobot(Robot *tRobot){robot = tRobot;}
void Mediator::registRobotSerial(RobotSerial* tRobotSerial){robotSerial = tRobotSerial;}
void Mediator::registPathPlan(PathPlan *tPathPlan) { pathPlan = tPathPlan;}

void Mediator::setPoint(int p)
{
	pathPlan->setPoint(p);
}
int Mediator::getSonarByIndex(int i)
{
	return robot->getSonarByIndex(i);
}
void Mediator::sendMsg(int n)
{
	robotSerial->sendMsg(n);
}
void Mediator::processData()
{
	robot->processData();
}

main.cpp

#include "robot.h"
#include "robotserial.h"
#include "pathplan.h"
#include "mediator.h"

int main()
{
	Mediator media;
	Robot robot(&media);
	RobotSerial robotSerial(&media);
	PathPlan pathPlan(&media);
	media.registRobot(&robot);
	media.registRobotSerial(&robotSerial);
	media.registPathPlan(&pathPlan);
	pathPlan.getSonarByIndex(1);
	robot.setPoint(1);

	robot.sendMsg(2);
	robotSerial.processData();
}

[C++]Bridge设计模式

2013年3月19日

Bridge模式定义 :
将抽象和行为划分开来,各自独立,但能动态的结合。

任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种具体表现,所以,“人”与“人的行为”两个概念也反映了抽象和行为之分。

在面向对象设计的基本概念中,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是一种抽象,一般情况下,行为是包含在一个对象中,但是,在有的情况下,我们需要将这些行为也进行归类,形成一个总的行为接口,这就是桥模式的用处。

为什么使用?
不希望抽象部分和行为有一种固定的绑定关系,而是应该可以动态联系的

如果一个抽象类或接口有多个具体实现(子类、concrete subclass),这些子类之间关系可能有以下两种情况:
1. 这多个子类之间概念是并列的,如举例,打桩,有两个实例:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复。

2.这多个子类之中有内容概念上重叠.那么需要我们把抽象共同部分行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口:抽象接口和行为接口,分别放置抽象和行为.

例如,一杯咖啡为例,子类实现类为四个:中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。

但是,我们注意到:上面四个子类中有概念重叠,可从另外一个角度进行考虑,这四个类实际是两个角色的组合:抽象 和行为,其中抽象为:中杯和大杯;行为为:加奶 不加奶(如加橙汁 加苹果汁).

实现四个子类在抽象和行为之间发生了固定的绑定关系,如果以后动态增加加葡萄汁的行为,就必须再增加两个类:中杯加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。

那我们从分离抽象和行为的角度,使用Bridge模式来实现。

如何实现?
以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.

抽象实例数为m,行为数为n,则可以进行m X n次组合。

来看看代码:
CoffeeImp.h

#ifndef _COFFEEIMP_H_
#define _COFFEEIMP_H_
class CoffeeImp
{
public:
	CoffeeImp();
	virtual ~CoffeeImp() = 0;
	virtual void Make();
};

class CoffeeImpSugar : public CoffeeImp
{
public:
	CoffeeImpSugar();
	~CoffeeImpSugar();
	void Make();
};

class CoffeeImpMilk : public CoffeeImp
{
public:
	CoffeeImpMilk();
	~CoffeeImpMilk();
	void Make();
};
#endif

CoffeeImp.cpp

#include "CoffeeImp.h"
#include
using namespace std;

CoffeeImp::CoffeeImp(){}
CoffeeImp::~CoffeeImp(){}
void CoffeeImp::Make(){}

CoffeeImpSugar::CoffeeImpSugar(){}
CoffeeImpSugar::~CoffeeImpSugar(){}
void CoffeeImpSugar::Make()
{
	cout<<"加糖"<<endl;
}

CoffeeImpMilk::CoffeeImpMilk(){}
CoffeeImpMilk::~CoffeeImpMilk(){}
void CoffeeImpMilk::Make()
{
	cout<<"加奶"<<endl;
}

Coffee.h

#ifndef _BRIDGE_H_
#define _BRIDGE_H_
class CoffeeImp;
class Coffee
{
public:
	Coffee();
	virtual ~Coffee() = 0;
	virtual void pourCoffee();
	void setCoffeeImp(CoffeeImp*);

protected:
	CoffeeImp *coffImp;
};

class BigCupCoffee : public Coffee
{
public:
	BigCupCoffee();
	~BigCupCoffee();
	void pourCoffee();
};

class SmallCupCoffee : public Coffee
{
public:
	SmallCupCoffee();
	~SmallCupCoffee();
	void pourCoffee();
};
#endif

Coffee.cpp

#include "Coffee.h"
#include "CoffeeImp.h"
#include "iostream"
using namespace std;

Coffee::Coffee(){}
Coffee::~Coffee(){}
void Coffee::setCoffeeImp(CoffeeImp *imp)
{
	coffImp = imp;
}
void Coffee::pourCoffee(){}

BigCupCoffee::BigCupCoffee(){cout<<"大杯";} 
BigCupCoffee::~BigCupCoffee(){} 
void BigCupCoffee::pourCoffee() 
{
 	coffImp->Make();
}
SmallCupCoffee::SmallCupCoffee(){cout<<"小杯";} 
SmallCupCoffee::~SmallCupCoffee(){} 
void SmallCupCoffee::pourCoffee() 
{
 	coffImp->Make();
}

main.cpp

#include "Coffee.h"
#include "CoffeeImp.h"

#include
using namespace std;

int main()
{
	CoffeeImp* coffeeImp = new CoffeeImpSugar();
	cout<<"Creater1想要:";
 	Coffee*	coffee = new BigCupCoffee(/*coffeeImp*/);
 	coffee->setCoffeeImp(coffeeImp);
	coffee->pourCoffee();
	delete coffeeImp, coffeeImp = 0;
	delete coffee, coffee = 0;
	cout<<"Creater2想要:";
 	coffeeImp = new CoffeeImpMilk();
 	coffee = new SmallCupCoffee();
 	coffee->setCoffeeImp(coffeeImp);
	coffee->pourCoffee();
	delete coffeeImp, coffeeImp = 0;
	delete coffee, coffee = 0;
	return 0;
}

结果为:

Creater1想要:大杯加糖
Creater2想要:小杯加奶

Factory Method与Abstract Factory

2013年3月18日

FactoryMethod是一个相对比较简单的创建型模式,但是能领悟或者用对的并不多见;很多示例都没有反应出Factory Method的核心思想,只是实现了一个简化版的Abstract Factory,然后给出的解释是Factory Method模式解决“单个对象”的需求变化,Abstract Factory 模式解决“系列对象”的需求变化。

试想一下,如果把1视为N的一种特殊情况,则一个产品系列可能只包含一个对象;那么我们是不是可以认为Factory Method是一个简化版的Abstract Factory呢?实际上,Factory Method模式与Abstract Factory模式虽然同属于对象创建型模式,并且AbstractFactory通常用Factory Method模式实现,并且效果上都可用于连接平行的类层次,但是这两个模式在思想上有着本质的区别。网上的文章抄来抄去,结果错误也被到处传。上一篇介绍了被普遍误用的Builder模式,这篇继续为Factory Method正名。 » 阅读更多: Factory Method与Abstract Factory