Upload
constantin-kichinsky
View
1.715
Download
3
Embed Size (px)
DESCRIPTION
Лекция Михаила Гуренкова по шаблонам проектирования в рамках курса по ООП. Каф. Вычислительная математика и программирование, МАИ.
Citation preview
Шаблоны проектирования
Часть вторая
Порождающие шаблоны
— Factory (фабрика, фабричный метод)
— Abstract Factory (абстрактная фабрика)
— Singleton (одиночка)
— Lazy Load (загрузка по требованию)
Façade (фасад)
Façade (фасад)class TreeNode{}
class SearchResult{}
static class ACAlgoritm{ public static TreeNode BuildTree(string[] a_Keywords)
{…
}
public static SearchResult[] FindAll(TreeNode a_Root, string a_Text){
…}
}
class SearchAlgoritm{ TreeNode m_Root; public SearchAlgoritm(string[] a_Keywords) { m_Root = ACAlgoritm.BuildTree(a_Keywords); }
public SearchResult[] FindAll(string a_Text) { return ACAlgoritm.FindAll(m_Root, a_Text); }
public static SearchResult[] FindAll(string[] a_Keywords, string a_Text)
{ return ACAlgoritm.FindAll(
ACAlgoritm.BuildTree(a_Keywords), a_Text);
}}
Façade (фасад)
— Предоставить более удобный интерфейс для использования библиотеки, за счет наличия специальных удобных методов
— Повысить читаемость клиентского кода (повышение уровня абстракции)
— Снизить связанность между клиентским кодом и кодом модуля
— Создать собственный хорошо спроектированный API для сторонней библиотеки, у которой свой API плохо спроектирован
Composite (компоновщик)
Composite (компоновщик)
select * from Companies
where (IsClient = 1 or IsFormerClient = 1) and IsDeleted = 0 and id_Object = 103
Composite (компоновщик)
IsClient = 1 or IsFormerClient = 1) and IsDeleted = 0 and id_Object = 103
and
or
IsClient = 1 IsFormerClient = 1
IsDeleted = 0 id_Object = 103
Composite (компоновщик)
interface IFilter{
string GetSql();}
interface ICompositeFilter : IFilter{
void AddFilter(IFilter a_Filter);}
Composite (компоновщик)class ScalarFilter : IFilter{ string m_Sql;
public ScalarFilter(string a_Field, string a_Relation, object a_Value) { m_Sql = string.Format("{0} {1} {2}", a_Field, a_Relation, a_Value); }
public ScalarFilter(string a_Field, object a_Value) : this (a_Field, "=", a_Value) {}
public string GetSql() { return m_Sql; }}
Composite (компоновщик)class AndFilter : ICompositeFilter{ List<IFilter> m_Filters = new List<IFilter>();
public void AddFilter(IFilter a_Filter) { m_Filters.Add(a_Filter); }
public string GetSql() { string result = string.Empty; foreach (IFilter filter in m_Filters) { if (result != "") result += " and "; result += filter.GetSql(); } return result; }}
Composite (компоновщик)protected IFilter GetFilterInternal(){ XAndFilter result = new XAndFilter(); if (ObjectsItemSelection.HasSelectedItems) { XOrFilter objectFilter = new XOrFilter(); foreach (XObject obj in ObjectsItemSelection.SelectedItems) objectFilter.Add(new XScalarFilter("id_Object", obj.Id)); result.Add(objectFilter); } if (OperatorCheckBox.Checked || ClientCheckBox.Checked || FormerClientCheckBox.Checked) { XAndFilter categoryFilter = new XAndFilter(); if (OperatorCheckBox.Checked) categoryFilter.Add(new XScalarFilter("IsOperator", 1)); if (ClientCheckBox.Checked) categoryFilter.Add(new XScalarFilter("IsClient", 1));
… result.Add(categoryFilter); } if (HoldingComboBox.Text.Trim() != "") { result.Add(DB.Companies.HoldingFilter(HoldingComboBox.Text.Trim())); } … return result;}
Composite (компоновщик)
Компоновщик — это круто!
Ахтунг!public class XScalarFilter : IFilter{ string m_Command; IDataParameter m_Parameter;
public XScalarFilter(string a_Field, string a_Relation, object a_Value) { int counter = XFilter.Counter; m_Command = string.Format("{0} {1} @p{2}", a_Field, a_Relation, counter); m_Parameter = new SqlParameter(); m_Parameter.Value = a_Value; m_Parameter.ParameterName = "@p" + counter; } public XScalarFilter(string a_Field, object a_Value) : this(a_Field, "=", a_Value) {}
public string SqlText { get { return m_Command; } }
public IList<IDataParameter> Parameters { get { return new IDataParameter[] { m_Parameter }; } }}
Задача
Command (команда)interface ICommand{ void Run();}
interface ICommand{ void Do(); void UnDo();}
foreach(ICommand command in GetCommands()){ command.Do();}
Command (команда)<?xml version='1.0' encoding='windows-1251'?><template> <parts> <part type="Cell" cell="Contract"> <sql>select ContractNumber from CompanyClients where id_Company = @id_Company</sql> </part> <part type="Cell" cell="CompName"> <sql>select FullName from Companies where id = @id_Company</sql> </part> <part type="Cell" cell="SmallCompName"> <sql>select FullName from Companies where id = @id_Company</sql> </part> <part type="Cell" cell="Month"> <sql>select @DateFrom</sql> </part> <part type="Table" cell="AbonTable" groupBy="BService"> <sql> select ... </sql> </part> </parts></template>
Command (команда)
Плагины[TemplateItem(TemplateKind.ExcelSpreadsheet, "Cell")]public class XCellTemplateItem : XTemplateItem{ public override void Apply() { XExcelWorkDesk wd = (XExcelWorkDesk)WorkDesk;
… }}
[TemplateItem(TemplateKind.ExcelSpreadsheet, "Table")]class XTableTemplateItem : XTemplateItem{}
ПлагиныType FindTypeByName(string a_Name){ foreach (Type type in GetType().Assembly.GetTypes()) { if (!type.IsSubclassOf(typeof(XTemplateItem))) { continue; }
if (!type.IsDefined(typeof(TemplateItemAttribute), false)) { continue; }
TemplateItemAttribute attr = (TemplateItemAttribute)type.GetCustomAttributes(typeof(TemplateItemAttribute), false)[0];
if (attr.TemplateKind == m_Template.TemplateKind && attr.Name == a_Name) { return type; } }
return null;}
Template Method (шаблонный метод)abstract class Game { protected int playersCount; protected abstract void initializeGame(); protected abstract void makePlay(int player); protected abstract bool endOfGame(); protected abstract void printWinner(); /* A template method : */ public void playOneGame(int playersCount) { this.playersCount = playersCount; initializeGame(); int j = 0; while (!endOfGame()) { makePlay(j); j = (j + 1) % playersCount; } printWinner(); }}
Template Method (шаблонный метод)abstract public class XParser{
public XCallInformation ParseAndProcess(XBillingString a_BillingString) {
a_BillingString.SetParser(this);
XCallInformation result = DoParse(a_BillingString);
if (result == null) { XBilling.RegisterError(a_BillingString); }
return result;}
public XCallInformation Parse(XBillingString a_BillingString){
a_BillingString.SetParser(this); return DoParse(a_BillingString);}
}
Strategy (стратегия)class XDocumentConflictManager{ public XDocumentConflict FindConflict(
XDocument a_Document, bool a_ForRegisteration) { XDocumentConflictFindingStrategy strategy =
XDocumentConflictFindingStrategy.Create(a_Document, a_ForRegisteration);
return new XDocumentConflict(a_Document, strategy.FindSameDocuments(), strategy);
}}
Strategy (стратегия)public abstract class XDocumentConflictFindingStrategy{ XDocument m_Document;
protected XDocumentConflictFindingStrategy(XDocument a_Document) { m_Document = a_Document; }
public static XDocumentConflictFindingStrategy Create(XDocument a_Document, bool a_ForRegistration)
{…
}
public IList<XDocument> FindSameDocuments() { return XDocumentRepository.Instance.Find(GetSameDocumentsFilter()); }
protected abstract IFilter GetSameDocumentsFilter();
public abstract string GetConflictDefinition();}
Strategy (стратегия) public class XBillingConflictFindingStrategy : XDocumentConflictFindingStrategy { internal XBillingConflictFindingStrategy(XDocument a_Document) : base(a_Document) {
}
protected override IFilter GetSameDocumentsFilter() { return new XAndFilter( DB.vDocuments.idFilter("!=", Document.Id), DB.vDocuments.id_CompanyFilter(Document.Company.Id), DB.vDocuments.DocumentDateFilter(Document.DocumentDate), DB.vDocuments.id_TemplateFilter(Document.Template.Id) ); }
public override string GetConflictDefinition() { return string.Format("Компания «{0}» уже имеет расшифровку «{1}» за «{2:MMMM yyyy}».", Document.Company.Alias, Document.Template.Name, Document.DocumentDate); } }