现代软件设计特征:需求频繁变化

设计模式的要点是“寻找变化点”,在变化点应用设计模式,从而更好的应对需求变化。

1、 Template Method

在软件构建结构中,往往他有整体的稳定结构,但是各个子步骤确有变化的需求,或者因为固有的原因(比如框架和应用之间)而无法和任务的整体结构同时实现。

这个时候往往使用Template Method方法。

定义一个操作中算法的骨架(稳定),而将一些步骤延迟(变化)到子类(父类定义虚函数,在子类中具体实现)。使得子类可以不改变(复用)一个算法的结构即

可重定义override该算法的某些特定步骤。让框架调用应用程序而不是应用程序调用框架。“不要调用我让我来调用你”,晚绑定和早绑定的区别。

UML类图:

代码实例:


class Library {//稳定的数据结构,不会发生改变
public:
void step1() {}
int step2() { return contrl;}
void virtual step3() {}
void step4() {}
void virtual step5() {} void run() {
step1();
if(step2()) {
step3();
}
else {
step5();
} for(int i = 10; i < 100; ++i) {
step4();
}
} virtual ~Library() {}; std::string name = "myname";
}; class Application1 : public Library {// 承载着不断变化的需求
public:
void step3() override { std::cout << this->name << std::endl; }
void step5() override { std::cout << this->Library::name << std::endl; }
std:: string name = "Application";
}; class Application2 : public Library {// 承载者不断变化的需求
public:
void step3() override {}
void step5() override {}
}; int main() {
Library *a = new Application1;
a->run();
delete a;
return 0;
}

2、 策略模式(Strategy)

在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中去,将会使得对象变得异常复杂,而且有时候支持几乎不使用的算法也是一种性能负担。

问题:如何在运行的时候根据需要透明的改变算法? 将算法与对象本身解耦合,从而避免上述问题?
定义:定义一系列算法,将他们一个个封装起来,而且他们可以相互替换(变化)。该模式使得算法可以独立于使用他们的应用程序(稳定)而变化(扩张,子类化)

UML类图:

代码实例:

class Strategy {
public:
virtual int doOperation(int num1, int num2) {} // 基类中需要改写的方法
virtual ~Strategy(){}
}; class plus final : public Strategy {// 不同的策略
public:
int doOperation(int num1, int num2) {
return num1 + num2;
}
}; class multipl final : public Strategy {
public:
int doOperation(int num1, int num2) {
return num1 * num2;
}
}; class minus final : public Strategy {
public:
int doOperation(int num1, int num2) {
return num1 - num2;
}
}; class Context { //封装调用接口
public:
Context(Strategy *init) :stra(init) {}
int run(int num1, int num2) {
return this->stra->doOperation(num1, num2);
}
private:
Strategy *stra;
}; int main() {
Context demo(new multipl);
std::cout << demo.run(10, 20) << std::endl; //使用调用接口中的基类指针多态的执行。
return 0;
}

3、 观察者模式(Observer)

一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。

一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。

一个对象必须通知其他对象,而并不知道这些对象是谁。

定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

UML类图:

代码示例:

enum class msg {
RETURN1,
RETURN2,
RETURN3
}; class Observer {
public:
void virtual update(msg ms) = 0;
}; class ob1 : public Observer {
public:
void update(msg ms) {
switch(ms) {
case msg::RETURN1 :
case msg::RETURN2 :
case msg::RETURN3 :
std::cout << "RETURN1" << std::endl;
default:
std::cout << "right" << std::endl;
}
}
}; class ob2 : public Observer {
public:
void update(msg ms) {
switch(ms) {
case msg::RETURN1 :
case msg::RETURN2 :
case msg::RETURN3 : {
std::cout << "RETURN2" << std::endl;
break;
}
default:
std::cout << "erro ms2" << std::endl;
}
}
}; class ob3 : public Observer {
public:
void update(msg ms) {
switch(ms) {
case msg::RETURN1 :
case msg::RETURN2 :
case msg::RETURN3 : {
std::cout << "RETURN3" << std::endl;
break;
}
default:
std::cout << "erro ms3" << std::endl;
}
}
}; class subject {
public:
void addob(Observer *ob) { obs.insert(ob);}
void removeob(Observer *ob) {
auto rob = obs.find(ob);
if(rob != obs.end()){
obs.erase(ob);
}
else std::cout << "erro no matching observer" << std::endl;
}
void update() {
for(auto& ob : obs) {
ob->update(ms);
}
} msg ms;
std::set<Observer*> obs;
}; int main() {
Observer *ob_1 = new ob1;
Observer *ob_2 = new ob2;
Observer *ob_3 = new ob3;
subject *sub = new subject;
sub->ms = msg::RETURN1;
sub->addob(ob_1);
sub->addob(ob_2);
sub->addob(ob_3);
sub->update();
return 0;
}

observer:变化尽量通过调用方的多态机制,传递给被调用方,决定如何调用。

最新文章

  1. javaScript代码执行顺序
  2. webpack 编译完成执行代码
  3. asp.net 页面的Meta元素
  4. Response.Redirect 打开新窗体的两种方法
  5. TortoiseSVN使用方法 安装和配置
  6. Linux学习 -- Shell编程 -- 字符处理命令
  7. ASP.NET Core MVC 中设置全局异常处理方式
  8. Andrew Ng机器学习课程笔记--week9(上)(异常检测&amp;推荐系统)
  9. 利用神经网络算法的C#手写数字识别
  10. 不要用for循环去遍历LinkedList
  11. CSS备战春招の二
  12. 开源协议瞎扯淡,什么是 MIT 协议?[转]
  13. (转)ReentrantLock实现原理及源码分析
  14. Aras 引入外部的dll
  15. Python-Django 路由控制器
  16. 大臣的旅费---树的直径(dfs)
  17. message [Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property
  18. Python中的format函数
  19. Linux 双向 SSH 免密登录
  20. 实现字符串函数,strlen(),strcpy(),strcmp(),strcat()

热门文章

  1. 天啦噜!知道硬盘很慢,但没想到比 CPU L1 Cache 慢 10000000 倍
  2. tslib-1.4移植(转)
  3. ZooKeeper伪分布式集群安装及使用
  4. EDI模拟实验
  5. 不要以为Bug写的好就是好程序员,其实这只占不到15%!
  6. 后羿:我射箭了快上—用MotionLayout实现王者荣耀团战
  7. css中伪元素before或after中content的特殊用法attr【转】
  8. ThreeJS学习6_几何体相关(BufferGeometry)
  9. Python入门教程完整版(懂中文就能学会)
  10. 4. Validator校验器的五大核心组件,一个都不能少