Demo
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)
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.
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:
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.
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.
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”.
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.
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’.”
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.==
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种工厂模式都是创建型模式,都是创建对象的,但都把产品具体创建的过程给隐藏了。
工厂方法模式是针对一种产品结构,而抽象工厂模式是针对多种产品结构。
在以下情况下应当考虑使用抽象工厂模式:
(以上资料来自于: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.
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();
}
MotifButton
MotifButton
MotifMenu
MotifMenu
MotifButton
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();
}
WindowsButton
WindowsButton
WindowsMenu
WindowsMenu
WindowsButton