連載:麵向對象葵花寶典:思想、技巧與實踐(39) - 設計原則 vs 設計模式
又是設計原則,又是設計模式,到底該用哪個呢? =============================================================================
在“設計模型”一章中,我們提到設計原則和設計模式是互補的,設計原則和設計模式互補體現在:設計原則主要用於指導“類的定義”的設計,而設計模式主要用於指導“類的行為”的設計。
舉一個很簡單的例子:假設我們要設計一個圖形類Shape,這個類既支持三角形,又支持矩形,其代碼如下:
package com.oo.designpattern.diagram;
/**
* 設計不好的Shape類,同時兼顧三角形和矩形的職責,不符合SRP設計原則
*
*/
public class BadShape {
//三角形的屬性
Position a;
Position b;
Position c;
//矩形的屬性
Position m;
int length;
int width;
public void drawTriangle(){
//TODO: 畫出三角形
}
public void drawRectangle(){
//TODO: 畫出矩形
}
}
有經驗的朋友都會覺得這個設計不太合理,因為其不符合類的SRP設計原則。因此,合理的做法是將這個類按照SRP原則拆分,具體拆分方法如下:
NormalShape.java
package com.oo.designpattern.diagram;
/**
* 將BadShape拆開為三角形和矩形兩個圖形,並提取出NormalShape這個父類
*
*/
abstract class NormalShape {
abstract void draw();
}
NormalTriangle.java
package com.oo.designpattern.diagram;
/**
* 三角形類
*
*/
public class NormalTriangle extends NormalShape {
//三角形的屬性
Position a;
Position b;
Position c;
@Override
public void draw() {
// TODO:繪畫三角形
if(Config.CURRENT_SYSTEM == Config.WINDOWS){
//TODO: 調用Windows的畫圖方法
}
else if( Config.CURRENT_SYSTEM == Config.LINUX){
//TODO: 調用Linux的畫圖方法
}
else if( Config.CURRENT_SYSTEM == Config.MAC){
//TODO: 調用Mac的畫圖方法
}
}
}
NormalRectangle.java
package com.oo.designpattern.diagram;
/**
* 矩形類
*
*/
public class NormalRectangle extends NormalShape {
//矩形的屬性
Position m;
int length;
int width;
@Override
public void draw() {
// TODO: 繪畫矩形
if(Config.CURRENT_SYSTEM == Config.WINDOWS){
//TODO: 調用Windows的畫圖方法
}
else if( Config.CURRENT_SYSTEM == Config.LINUX){
//TODO: 調用Linux的畫圖方法
}
else if( Config.CURRENT_SYSTEM == Config.MAC){
//TODO: 調用Mac的畫圖方法
}
}
}
這樣拆分之後,從類的設計原則來看,已經是符合要求了。
接下來我們再使用設計模式來繼續完善這個設計,這裏就需要使用設計模式之道來指導我們設計了,即:找到變化,封裝變化。
關於圖形類一個比較明顯的變化是跨平台,比如說要同時支持Windows、Linux、Mac三個桌麵操作係統,那麼實際畫圖的方法和需要調用的函數可能就隨著平台的不同而變化,因此我們要找出一種方法來封裝這種變化。
參考《設計模式》,可以知道這種方法就是“Bridge模式”,使用了Bridge後,會多出幾個接口和實現類。
具體實現如下:
GoodShape.java
package com.oo.designpattern.diagram;
/**
* 在NormalShape的基礎上,增加Bridge設計模式的實現,使其更加適應於跨平台
*
*/
abstract public class GoodShape {
protected ShapeDraw _draw; //將不同平台的實現封裝到一個新的接口ShapeDraw
abstract void draw();
}
GoodTriangle.java
package com.oo.designpattern.diagram;
/**
* 按照Bridge設計模式設計的三角形類
*
*/
public class GoodTriangle extends GoodShape {
GoodTriangle(ShapeDraw draw){
this._draw = draw;
}
@Override
void draw() {
// TODO Auto-generated method stub
this._draw.drawTriangle();
}
}
GoodRectangle.java
package com.oo.designpattern.diagram;
/**
* 按照Bridge設計模式設計的矩形類
*
*/
public class GoodRectangle extends GoodShape {
GoodRectangle(ShapeDraw draw){
this._draw = draw;
}
@Override
void draw() {
// TODO Auto-generated method stub
this._draw.drawRectangle();
}
}
ShapeDraw.java
package com.oo.designpattern.diagram;
/**
* 按照Bridge設計模式進行設計的畫圖的接口,封裝了跨平台不同的實現
*
*/
interface ShapeDraw {
public void drawTriangle();
public void drawRectangle();
}
WindowsDraw.java
package com.oo.designpattern.diagram;
/**
* Windwos上的畫圖實現
*
*/
public class WindowsDraw implements ShapeDraw {
@Override
public void drawTriangle() {
// TODO Auto-generated method stub
}
@Override
public void drawRectangle() {
// TODO Auto-generated method stub
}
}
LinuxDraw.java
package com.oo.designpattern.diagram;
/**
* Linux上的畫圖實現
*
*/
public class LinuxDraw implements ShapeDraw {
@Override
public void drawTriangle() {
// TODO Auto-generated method stub
}
@Override
public void drawRectangle() {
// TODO Auto-generated method stub
}
}
MacDraw.java
package com.oo.designpattern.diagram;
/**
* Mac上的畫圖實現
*
*/
public class MacDraw implements ShapeDraw {
@Override
public void drawTriangle() {
// TODO Auto-generated method stub
}
@Override
public void drawRectangle() {
// TODO Auto-generated method stub
}
}
可以看到,按照設計原則和設計模式進行重構後,原來不合理的設計逐步演變為一個優秀的設計了
================================================
轉載請注明出處:https://blog.csdn.net/yunhua_lee/article/details/38655873
================================================
最後更新:2017-04-03 05:39:54