[C++]polymorphic and OOP design pattern Abstract Factory(抽象工厂模式)

抽象工厂模式

Demo

OOP Design Principles

There are five common recognized principles in object-oriented design. These principles, when combined together, make it easy for a programmer to develop software that are easy to maintain and extend. They also make it easy for developers to avoid code smells, easily refactor code, and are also a part of the agile or adaptive software development.They are: (from wikipedia)

1. Single Responsibility Principle

The single responsibility principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility. Robert C. Martin expresses the principle as follows.

2. Liskov Substitution Principle

Substitutability is a principle in obaject-oriented programming. It states that, in a computer program, if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may substitute objects of type T) without altering any of the desirable properties of that program (correctness, task performed, etc.). More formally, the Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping, that was initially introduced by Barbara Liskov in a 1987 conference keynote address entitled Data abstraction and hierarchy. It is a semantic rather than merely syntactic relation because it intends to guarantee semantic interoperability of types in a hierarchy, object types in particular. Barbara Liskov and Jeannette Wing formulated the principle succinctly in a 1994 paper as follows:

3.Dependency inversion principle

In object-oriented programming, the dependency inversion principle refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states:

High-level modules should not depend on low-level modules. Both should depend on abstractions.

Abstractions should not depend on details. Details should depend on abstractions.

4. Interface segregation principle

The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.[1] ISP splits interfaces which are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called role interfaces.[2] ISP is intended to keep a system decoupled and thus easier to refactor, change, and redeploy. ISP is one of the five SOLID principles of Object-Oriented Design, similar to the High Cohesion Principle of GRASP.

5. Law of Demeter

The Law of Demeter (LoD) or principle of least knowledge is a design guideline for developing software, particularly object-oriented programs. In its general form, the LoD is a specific case of loose coupling. The guideline was proposed at Northeastern University towards the end of 1987, and can be succinctly summarized in each of the following ways:

Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.

Each unit should only talk to its friends; don’t talk to strangers.

Only talk to your immediate friends.

The fundamental notion is that a given object should assume as little as possible about the structure or properties of anything else (including its subcomponents), in accordance with the principle of “information hiding”.

6. Open/closed principle

In object-oriented programming, the open/closed principle states “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”; that is, such an entity can allow its behaviour to be extended without modifying its source code.

The name open/closed principle has been used in two ways. Both ways use inheritance to resolve the apparent dilemma, but the goals, techniques, and results are different.

7. Composition over inheritance

Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class.[2] This is an often-stated principle of OOP, such as in the influential Design Patterns: “Favor ‘object composition’ over ‘class inheritance’.”

OOP design Patterns:

From the design principles, there are about 23 OOP design patterns:

Singleton(单例模式), which you have had an assignment name “JobManager”, and this is the most easy parttern.
Factory(Simplified version of Factory Method)
Factory Method
Abstract Factory
Builder
Prototype
and so on …

This time we discuss with ==Abstract Factory Pattern.==

Abstract Factory Pattern

Offers the interface for creating a family of related objects, without explicitly specifying their classes.

This will use inheritance and polymorphic in C++.

理解:

问题的产生:

在系统里a,b,c三个组件必须同时使用,但是a的同类 a1和a2这三种方法有共同特点但是是互斥的,b,b1,b2和c,c1,c2和a/a1/a2是一样的。就比如说创建在不同操作系统的视窗环境下都能够运行的系统时,Unix下面有unixButton和 unixText,Win下面也有winButton和winText,unixButton和unixText必须在一个系统unix里面用,而winButton和winText只能在Win下面用。但是winButton和unixButton这两种东西都是有相同的特点的,比如说按下去之后会触发事件,比如说他上面有文字描述等等,但是winButton和unixButton却又是不可以混用的。

那么此问题就可以用抽象工厂很好的解决:

在抽象工厂模式中如何选择使用 winButton ,winText,有具体的工厂类winFactory来负责,因为他们含有选择合适的产品对象的逻辑,所以是与应用系统的商业逻辑紧密相关的。而==抽象工厂类来负责定义接口==,他才是抽象工厂模式的核心。

而winButton/macButton则是一种产品族,==有共同的特点,他们具体特点有抽象产品类或者接口来定义和描述==。但是他们具体的实现有具体的产品类负责,这些是客户端最终想要的东西,所以其内部一定充满了应用系统的商业逻辑(触发逻辑/样式逻辑等)。

类图结构:
类图结构

“开放-封闭”原则:

抽象工厂可以很好的应对增加新产品族的问题(即a4/b4/c4),且符合“开放-封闭”原则,但是若是增加新的产品结构的话(即d/d1/d2),就是说a/b/c/d这4中方法必须同时使用了,那就必须修改工厂角色。不符合“开放-封闭”原则。综合来讲,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品结构的增加提供这样的方便。

实现要点:

在抽象工厂模式中,选用哪种产品族的问题,需要==采用工厂方法或简单工厂模式来配合解决==。
抽象工厂模式和工厂方法模式一样,都把==对象的创建延迟到了他的子类中==。
具体的工厂类可以设计成单例类,他只向外界提供自己唯一的实例。

与其他工厂模式的联系和异同:
抽象工厂模式中的==具体工厂负责生产一个产品族的产品==。而产品族的增加只需要增加与其对应的具体工厂。
3种工厂模式都是创建型模式,都是创建对象的,但都把产品具体创建的过程给隐藏了。
工厂方法模式是针对一种产品结构,而抽象工厂模式是针对多种产品结构。

适用性:

在以下情况下应当考虑使用抽象工厂模式:

  1. 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
  2. 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
  3. 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
  4. 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。

(以上资料来自于:http://www.tuicool.com/articles/7ZfYZj。)

实例:

Trying to maintain portability across multiple “platforms” routinely requires lots of preprocessor “case” statements. The Factory pattern suggests defining a creation services interface in a Factory base class, and implementing each “platform” in a separate Factory derived class.

Before:

The client creates “product” objects directly, and must embed all possible platform permutations in nasty looking code.

#define MOTIF

class Widget {
public:
   virtual void draw() = 0;
};

class MotifButton : public Widget {
public:
   void draw() { cout << "MotifButton\n"; }
};
class MotifMenu : public Widget {
public:
   void draw() { cout << "MotifMenu\n"; }
};

class WindowsButton : public Widget {
public:
   void draw() { cout << "WindowsButton\n"; }
};
class WindowsMenu : public Widget {
public:
   void draw() { cout << "WindowsMenu\n"; }
};

void display_window_one() {
#ifdef MOTIF
   Widget* w[] = { new MotifButton,
                   new MotifMenu };
#else // WINDOWS
   Widget* w[] = { new WindowsButton,
                   new WindowsMenu };
#endif
   w[0]->draw();  w[1]->draw();
}

void display_window_two() {
#ifdef MOTIF
   Widget* w[] = { new MotifMenu,
                   new MotifButton };
#else // WINDOWS
   Widget* w[] = { new WindowsMenu,
                   new WindowsButton };
#endif
   w[0]->draw();  w[1]->draw();
}

int main() {
#ifdef MOTIF
   Widget* w = new MotifButton;
#else // WINDOWS
   Widget* w = new WindowsButton;
#endif
   w->draw();
   display_window_one();
   display_window_two();
}
Output
MotifButton
MotifButton
MotifMenu
MotifMenu
MotifButton
After:

The client: creates a platform- specific “factory” object, is careful to eschew use of “new”, and delegates all creation requests to the factory.

#define WINDOWS

class Widget {
public:
   virtual void draw() = 0;
};

class MotifButton : public Widget {
public:
   void draw() { cout << "MotifButton\n"; }
};
class MotifMenu : public Widget {
public:
   void draw() { cout << "MotifMenu\n"; }
};

class WindowsButton : public Widget {
public:
   void draw() { cout << "WindowsButton\n"; }
};
class WindowsMenu : public Widget {
public:
   void draw() { cout << "WindowsMenu\n"; }
};

class Factory {
public:
   virtual Widget* create_button() = 0;
   virtual Widget* create_menu() = 0;
};

class MotifFactory : public Factory {
public:
   Widget* create_button() {
      return new MotifButton; }
   Widget* create_menu()   {
      return new MotifMenu; }
};

class WindowsFactory : public Factory {
public:
   Widget* create_button() {
      return new WindowsButton; }
   Widget* create_menu()   {
      return new WindowsMenu; }
};

Factory* factory;

void display_window_one() {
   Widget* w[] = { factory->create_button(),
                   factory->create_menu() };
   w[0]->draw();  w[1]->draw();
}

void display_window_two() {
   Widget* w[] = { factory->create_menu(),
                   factory->create_button() };
   w[0]->draw();  w[1]->draw();
}

int main() {
#ifdef MOTIF
   factory = new MotifFactory;
#else // WINDOWS
   factory = new WindowsFactory;
#endif

   Widget* w = factory->create_button();
   w->draw();
   display_window_one();
   display_window_two();
}
output:
WindowsButton
WindowsButton
WindowsMenu
WindowsMenu
WindowsButton
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值