大家把自己关于设计模式的问题和心得什么的拿出来共享吧?(yysun老师,cheka,左轻侯,房客,wjiachun,吴剑明,cAkk,千中元,雁孤行,吕雪松,g

  • 主题发起人 主题发起人 VRGL
  • 开始时间 开始时间
把家搬来,随时学习.
 
好久没上了,也说两句吧:P
我认为设计模式和商业利益有关,与项目属性有关。
特别是在批量销售的软件中,代码的可重用要求比较高,这涉及到生产效率的问题。
而共享及免费软件中,以代码的效率见长。
因为目的的不同,设计模式也有开始分化。
设计模式的重要性与项目规模相关。
如果程序规模很小,我想设计模式可能偏重于个人的习惯。(最好是有,这样会养成良好
的习惯)
如果程序规模很庞大,设计模式的确立,对项目的进度、效率以及实施的难易将起很大的
影响。因为程序规模的展开,实施人员的规模也相应增大。设计模式就形成了整体的利益
。个人习惯与整体要求反方向增长。
至于,设计模式的学习与应用方法,那VRGL和YYSUN是高手中的高手中的高手……嘿嘿
我就不班门弄斧了。
因为做了几个比较大的项目,而且是我总统筹,所以对设计模式的应用的重要性,我认为
相当重要,特别是对商业利益。有钱赚多好呀:)
 
不说理论了, 我出个题目, 大家作一下, 看谁的设计模型最好。
思路是设计engine系统中的外挂模块, 象Apache中的Model, 或Winamp中的Plug-In。
要求是engine可根据ini或database文件去装载模块, 模块变更不须重编译engine,
模块中的过程支持MultiThreading 和 Event call back,例如,
engine 调用模块中的过程象Start_?, Stop_?, GetProgress_?..
 
VRGL加我的QQ1473155
 
我也来听听!:)
 
水平高的可以看看:
机械工业出版社的<<设计模式>>
 
初,编程时,我只看到代码。
做完一个项目后,再编程,我看到的是子过程……
现在我在研究怎样编程,目标是:我看到的是对象。
这个问题一直困惑了我很长一段时间,几月下来,我还是不能看到我爱的对象。希望高手指
点迷津:
1、到底要多少类?
2、怎么样把类和对函数/过程的简单组合分开?即:类不是一群函数的简单组合。
3、为什么我看到的类总是那么少?
4、为什么我看到的类总是像一堆函数?
5、为什么说类是可重复使用的,而我的类只用了一次?
6、为什么我每次新写程序的时候,又在写一些我写过的类?
7、为什么用类开发数据库应用的时候,感觉写类就像打字一样?
8、为什么Object Pascal也是oo的,可我却买不到一本讲Delphi OOP方面的书?
9、为什么DELPHI高手写的Code看起来就是那么烦琐,乖僻。除了让人觉得他们是一些Delphi
库的高手以外,很少让人觉得他们是OOP高手?
…………
不胜枚举。还有很多问题等我先把上面这些问题弄明白之后再问了……
 
抛块砖吧,
Here is some code fragment of engine module I wrote,
first one is a event callback interface,
another is a threaded data module
full sample is at the http://delphi.mychangshu.com/dispdoc.asp?id=867.
any opinions are welcome.
unit uThreadedInterfaces;
interface

type
IThreadedCallback = interface
['{4BBBBB77-1341-4597-B731-BB2655F8F1C7}']
function GetMin: integer;
procedure SetMin(AValue: integer);
property Min: integer read GetMin write SetMin;
function GetMax: integer;
procedure SetMax(AValue: integer);
property Max: integer read GetMax write SetMax;
function GetProgress: integer;
procedure SetProgress(AValue: integer);
property Progress: integer read GetProgress write SetProgress;
function GetStatusMessage: string;
procedure SetStatusMessage(AValue: string);
property StatusMessage: string read GetStatusMessage write SetStatusMessage;
procedure ModuleFinished;
end;

IThreadedDataModule = interface
['{CD367799-3F0B-46D4-89DE-E8E6CD5F5F92}']
function GetCallback: IThreadedCallback;
procedure SetCallback(AValue: IThreadedCallback);
property Callback: IThreadedCallback read GetCallback write SetCallback;
function GetParamByName(AParam: string): string;
procedure SetParamByName(AParam, AValue: string);
property ParamByName[AParam: string]: string read GetParamByName write SetParamByName;
procedure Execute;
procedure Pause;
procedure Resume;
procedure Terminate;
end;

IThreadedManager = interface
['{2D9215CE-C76C-4468-AF91-6CC9D9D6B49C}']
function ThreadedDatamodule(ThreadIndex: integer): IThreadedDataModule;
end;

IThreadedStatusManager = interface
['{0E0CDF80-9C09-4D61-B6BC-6C0AE67A9DA1}']
procedure ThreadCreated(ThreadIndex: integer);
end;

unit uThreadedDataModule;
interface
uses
SysUtils, Classes, uThreadedInterfaces, Forms;
type
TdmThreadedDataModule = class;
TdmThreadedDataModuleClass = class of TdmThreadedDataModule;
// Manages a list of threaded datamodules
TModuleList = class(TObject)
private
FModuleList: TList;
function GetCount: integer;
function GetModule(index: integer): IThreadedDataModule;
public
constructor Create;
destructor Destroy;
override;
procedure Add(Module: IThreadedDataModule);
procedure Remove(Module: IThreadedDataModule);
property Count: integer read GetCount;
property Module[index: integer]: IThreadedDataModule read GetModule;

end;

TModuleThread = class(TThread)
private
FDataModule: TdmThreadedDataModule;
public
constructor Create(ADataModule: TdmThreadedDatamodule);
procedure Execute;
override;
end;

TdmThreadedDataModule = class(TDataModule, IThreadedDataModule)
private
{ Private declarations }
FCallback: IThreadedCallback;
FParams: TStringList;
FThread: TModuleThread;
FList: TModuleList;
function GetTerminated: boolean;
private
// Utility functions passed to the thread for display..
FMax, FMin, FProgress: integer;
FStatusMessage: string;
proceduredo
GetMax;
proceduredo
GetMin;
proceduredo
GetProgress;
proceduredo
SetMax;
proceduredo
SetMin;
proceduredo
SetProgress;
proceduredo
GetStatusMessage;
proceduredo
SetStatusMessage;
protected
// IInterface
FReferenceCount: integer;
function _AddRef: Integer;
stdcall;
function _Release: Integer;
stdcall;
// IThreadedDataModule
function GetCallback: IThreadedCallback;
procedure SetCallback(AValue: IThreadedCallback);
property Callback: IThreadedCallback read GetCallback write SetCallback;
function GetParamByName(AParam: string): string;
procedure SetParamByName(AParam, AValue: string);
property ParamByName[AParam: string]: string read GetParamByName write SetParamByName;
procedure Execute;
procedure Pause;
procedure Resume;
procedure Terminate;
protected
// Utility Functions used by the developer in the ModuleExecute method.
function GetMax: integer;
function GetMin: integer;
function GetProgress: integer;
procedure SetMax(const Value: integer);
procedure SetMin(const Value: integer);
procedure SetProgress(const Value: integer);
property Min: integer read GetMin write SetMin;
property Max: integer read GetMax write SetMax;
property Progress: integer read GetProgress write SetProgress;
function GetStatusMessage: string;
procedure SetStatusMessage(const Value: string);
property StatusMessage: string read GetStatusMessage write SetStatusMessage;
procedure ModuleFinished;
property Terminated: boolean read GetTerminated;
protected
class function ModuleName: string;
virtual;
public
{ Public declarations }
constructor Create(AOwner: TComponent);
override;
destructor Destroy;
override;
procedure ModuleExecute;
virtual;
end;

var
dmThreadedDataModule: TdmThreadedDataModule;
DataModules: TStringList;
procedure RegisterDataModule(ADataModule: TdmThreadedDataModuleClass);
function DataModuleCount: integer;
function DataModule(index: integer): IThreadedDataModule;
function DataModuleName(index: integer): string;

implementation
{$R *.dfm}
procedure RegisterDataModule(ADataModule: TdmThreadedDataModuleClass);
begin
if ADataModule <> nil then
DataModules.AddObject(ADataModule.ModuleName, TObject(ADataModule));
end;

function DataModuleCount: integer;
begin
Result:=DataModules.Count;
end;

function DataModule(index: integer): IThreadedDataModule;
begin
Result:=nil;
if index >= DataModules.Count then
Exit;
Result:=TdmThreadedDataModuleClass(DataModules.Objects[index]).Create(nil);
end;

function DataModuleName(index: integer): string;
begin
Result:='';
if index >= DataModules.Count then
Exit;
Result:=DataModules[index];
end;

{ TdmThreadedDataModule }

constructor TdmThreadedDataModule.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FParams:=TStringLIst.Create;
end;

destructor TdmThreadedDataModule.Destroy;
begin
FCallBack:=nil;
FParams.Destroy;
if FList <> nil then
FList.Remove(Self);
inherited Destroy;
end;

procedure TdmThreadedDataModule.DoGetMax;
begin
if FCallBack = nil then
Exit;
FMax:=FCallBack.Max;
end;

procedure TdmThreadedDataModule.DoGetMin;
begin
if FCallBack = nil then
Exit;
FMin:=FCallBack.Min;
end;

procedure TdmThreadedDataModule.DoGetProgress;
begin
if FCallBack = nil then
Exit;
FProgress:=FCallBack.Progress;
end;

procedure TdmThreadedDataModule.DoGetStatusMessage;
begin
if FCallback = nil then
Exit;
FStatusMessage:=FCallback.StatusMessage;
end;

procedure TdmThreadedDataModule.DoSetMax;
begin
if FCallBack = nil then
Exit;
FCallBack.Max:=FMax;
end;

procedure TdmThreadedDataModule.DoSetMin;
begin
if FCallBack = nil then
Exit;
FCallBack.Min:=FMin;
end;

procedure TdmThreadedDataModule.DoSetProgress;
begin
if FCallBack = nil then
Exit;
FCallBack.Progress:=FProgress;
end;

procedure TdmThreadedDataModule.DoSetStatusMessage;
begin
if FCallback = nil then
Exit;
FCallBack.StatusMessage:=FStatusMessage;
end;

procedure TdmThreadedDataModule.Execute;
begin
TModuleThread.Create(Self);
end;

function TdmThreadedDataModule.GetCallback: IThreadedCallback;
begin
Result:=FCallback;
end;

function TdmThreadedDataModule.GetMax: integer;
begin
Result:=-1;
if FThread = nil then
Exit;
do
GetMax;
Result:=FMax;
end;

function TdmThreadedDataModule.GetMin: integer;
begin
Result:=-1;
if FThread = nil then
Exit;
do
GetMin;
Result:=FMin;
end;

function TdmThreadedDataModule.GetParamByName(AParam: string): string;
begin
Result:=FParams.Values[AParam];
end;

function TdmThreadedDataModule.GetProgress: integer;
begin
Result:=-1;
if FThread = nil then
Exit;
do
GetProgress;
Result:=FProgress;
end;

function TdmThreadedDataModule.GetStatusMessage: string;
begin
Result:='';
if FThread = nil then
Exit;
// do
GetStatusMessage;
// Result:=FStatusMessage;
end;

function TdmThreadedDataModule.GetTerminated: boolean;
begin
Result:=False;
if FThread = nil then
Exit;
REsult:=FTHread.Terminated;
end;

procedure TdmThreadedDataModule.ModuleExecute;
begin
// Base classdo
es nothing.
end;

procedure TdmThreadedDataModule.ModuleFinished;
begin
if FCallBack <> nil then
FCallBack.ModuleFinished;
end;

class function TdmThreadedDataModule.ModuleName: string;
begin
// Children override to provide their name
Result:='BASE DATAMODULE CLASS';
end;

procedure TdmThreadedDataModule.Pause;
begin
// Pauses the thread.
if FThread = nil then
Exit;
FThread.Suspend;
end;

procedure TdmThreadedDataModule.Resume;
begin
// Resumes the thread.
if FThread = nil then
Exit;
FThread.Resume;
end;

procedure TdmThreadedDataModule.SetCallback(AValue: IThreadedCallback);
begin
FCallback:=AValue;
end;

procedure TdmThreadedDataModule.SetMax(const Value: integer);
begin
if FThread = nil then
Exit;
FMax:=Value;
do
SetMax;
end;

procedure TdmThreadedDataModule.SetMin(const Value: integer);
begin
if FThread = nil then
Exit;
FMin:=Value;
do
SetMin;
end;

procedure TdmThreadedDataModule.SetParamByName(AParam, AValue: string);
begin
FParams.Values[AParam]:=AValue;
end;

procedure TdmThreadedDataModule.SetProgress(const Value: integer);
begin
if FThread = nil then
Exit;
FProgress:=Value;
do
SetProgress;
end;

procedure TdmThreadedDataModule.SetStatusMessage(const Value: string);
begin
if FThread = nil then
Exit;
FStatusMessage:=Value;
do
SetStatusMessage;
end;

procedure TdmThreadedDataModule.Terminate;
begin
// Terminates the thread.
if FThread = nil then
Exit;
FThread.Terminate;
end;

function TdmThreadedDataModule._AddRef: Integer;
begin
Result:=-1;
// Inc(FReferenceCount);
// Result:=FReferenceCount;
end;

function TdmThreadedDataModule._Release: Integer;
begin
Result:=-1;
// Dec(FReferenceCount);
// Result:=FReferenceCount;
// if FReferenceCount = 0 then
// Destroy;
end;

{ TModuleThread }
constructor TModuleThread.Create(ADataModule: TdmTHreadedDatamodule);
begin
FreeOnTerminate:=True;
FDataModule:=ADataModule;
FDataModule.FThread:=Self;
inherited Create(False);
end;

procedure TModuleThread.Execute;
begin
try
FDataModule.ModuleExecute;
finally
FDataModule.Destroy;
end;
end;

{ TModuleList }
procedure TModuleList.Add(Module: IThreadedDataModule);
begin
FModuleList.Add(TObject(Module));
TdmThreadedDataModule(Module).FList:=Self;
end;

constructor TModuleList.Create;
begin
FModuleList:=TList.Create;
end;

destructor TModuleList.Destroy;
begin
// Assuming all modules are destroyed at this point.
FModuleList.Destroy;
inherited Destroy;
end;

function TModuleList.GetCount: integer;
begin
Result:=FModuleList.Count;
end;

function TModuleList.GetModule(index: integer): IThreadedDataModule;
begin
Result:=IThreadedDataModule(FModuleList[index]);
end;

procedure TModuleList.Remove(Module: IThreadedDataModule);
begin
FModuleList.Remove(TObject(Module));
TdmThreadedDataModule(Module).FList:=nil;
end;

initialization
DataModules:=TStringList.Create;
finalization
DataModules.Destroy;

end.



// DLL Exported methods
DataModuleCountFunc = function : integer;
DataModuleFunc = function (index: integer): IThreadedDataModule;
DataModuleNameFunc = function (index: integer): string;

implementation
end.
 
有关复用性的看法:
这是一个相对的概念。从复用性的角度来说,软件结构应该成为一种金字塔的结构。
底层的类具有很好的复用性,最顶层的类只适用于某一个领域。所有的类在设计上
的复用性考虑,都不应该也不可能超越该类所在的层次。我们在搭建一个新的软件
时,都是从最高层出发,向下寻找第一个可以复用的层次的类,最坏的情况是下到
最低层,那这样的工程就没什么复用可言了。所以理想的情况下,我们所有的工程
应该看起来像一棵树,有一套公共代码作为根基。根基越深厚,开发新项目的成本
就越低。
不过,复用性的好坏很大程度上取决于经验。
 
学习!!!
 
日本有一本UML的期刊,其中多篇文章都非常好,我正在翻译,只是时间问题。
其中有一篇给初学者的表格(指面向对象设计的初学者,不是开发初学者)
我觉得还挺实用的,讲的是什么样的软件功能对应什么样的类设计,挺有趣
的。有机会,贴上来。
 
TO Crane
可以改我看看原版吗?
我懂日语~~
3LOU@163.COM
 
算啦, 我把在手头项目中用到的及各设计模式贴上来吧...
unit Observer;
interface
uses
Classes;
type
TObserver = class;
TSubject = class;

TSubject = class(TObject)
private
FObservers: TList;

protected
proceduredo
Notify(Sender: TObject);
virtual;

public
constructor Create;
virtual;
destructor Destroy;
override;
procedure Notify(Sender: TObject);
virtual;
procedure Attach(aObserver: TObserver);
virtual;
procedure Detach(aObserver: TObserver);
virtual;
end;

TObserver = class(TObject)
private
FEnabled : Boolean;
FOnNotify: TNotifyEvent;
protected
proceduredo
OnNotify(Sender: TObject);
virtual;

published
property Enabled: Boolean read FEnabled write FEnabled;
property OnNotify: TNotifyEvent read FOnNotify write FOnNotify;
end;

implementation
constructor TSubject.Create;
begin
FObservers := TList.Create;
end;

destructor TSubject.Destroy;
begin
if Assigned(FObservers) then
FObservers.Free;
end;

procedure TSubject.doNotify(Sender: TObject);
var
Obs: TObserver;
I: Integer;
begin

for I := 0 to FObservers.Count-1do
begin

Obs := FObservers;
if Assigned(Obs) and Obs.Enabled then
Obs.doOnNotify(Sender);
end;

end;

procedure TSubject.Notify(Sender: TObject);
begin
do
Notify(Sender);
end;

procedure TSubject.Attach(aObserver: TObserver);
begin

if FObservers.IndexOf(aObserver) = -1 then
FObservers.Add(aObserver);
end;

procedure TSubject.Detach(aObserver: TObserver);
begin
FObservers.Remove(aObserver);
end;

procedure TObserver.doOnNotify(Sender: TObject);
begin

if Assigned(FOnNotify) then
FOnNotify(Sender);
end;

end.
 
后退
顶部