Skip to content

Instantly share code, notes, and snippets.

@EsProgram
Created Feb 17, 2014
Embed
What would you like to do?
/*
* 以下のコードは
* アラン・シャロウェイ,ジェームズ・R・トロット:著 / 村上 雅章:訳 / (2005) / 『デザインパターンとともに学ぶ オブジェクト指向のこころ』 / 株式会社ピアソン・エデュケーション
* より、自分なりにC#用に改変させていただいたコードです
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class DecoratorTest
{
static void Main(string[] args)
{
Factory myFactory = new Factory();
Component myComponent = myFactory.GetComponent1();
myComponent.PrintTicket();
Console.WriteLine();
myComponent = myFactory.GetComponent2();
myComponent.PrintTicket();
}
}
abstract class Component
{
/// <summary>
/// 伝票を印字する
/// </summary>
abstract public void PrintTicket();
}
class SalesTicket : Component
{
public override void PrintTicket()
{
//ここに伝票の内約が表示されます
Console.WriteLine("これは伝票の内約です");
}
}
abstract class TicketDecorator : Component
{
//再帰的に修飾機能を格納し、メイン機能は最後に1回格納する
Component myComponent;
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="c">Componentを継承する具象クラス</param>
public TicketDecorator(Component c)
{
myComponent = c;
}
/// <summary>
/// 保持しているComponentがnullでなければ
/// プリントアウトするメソッド
/// </summary>
public void CallTrailer()
{
if(myComponent != null)
myComponent.PrintTicket();
}
}
class Header1 : TicketDecorator
{
/// <summary>
/// myComponentはprivateなのでこのクラス内からではアクセス不可
/// よって、スーパークラスのコンストラクタを呼び出す
///
/// privateなメンバではあるが、このクラス内に複製されているものとして扱える
/// スーパークラスのmyComponentを操作しているわけではないので注意
///
/// 特にこのクラスでのみ特別にスーパークラスのメンバを扱わない場合は
/// protectedとして継承するよりはprivateのまま継承して、初期化させてしまう方が
/// このクラス内で下手に変更してしまう危険性がなくなるため、この手法を利用する
/// </summary>
/// <param name="c">Componentを継承する具象クラス</param>
public Header1(Component c) : base(c) { }
public override void PrintTicket()
{
//メソッドの呼び出し順に気をつけましょう
//まずはヘッダなので先に出力します(自分の出力)
//その後、保持しているComponentの出力メソッドを呼び出すようにしています
//自分の出力
Console.WriteLine("ヘッダ1を出力しました");
//保持しているComponentの出力メソッドを呼び出す
CallTrailer();
}
}
class Header2 : TicketDecorator
{
public Header2(Component c) : base(c) { }
public override void PrintTicket()
{
Console.WriteLine("ヘッダ2を出力しました");
CallTrailer();
}
}
class Footer1 : TicketDecorator
{
public Footer1(Component c) : base(c) { }
public override void PrintTicket()
{
//ここでも呼び出し順に注意です
//先にComponentへの参照から出力させ
//その後、自分の出力をします
CallTrailer();
Console.WriteLine("フッタ1を出力しました");
}
}
class Footer2 : TicketDecorator
{
public Footer2(Component c) : base(c) { }
public override void PrintTicket()
{
CallTrailer();
Console.WriteLine("フッタ2を出力しました");
}
}
class Factory
{
/// <summary>
/// ヘッダ1
/// ヘッダ2
/// 内約
/// フッタ1
/// フッタ2
/// を印字する
/// </summary>
/// <returns>印字に必要なオブジェクト群</returns>
public Component GetComponent1()
{
return new Header1(new Header2(new Footer2(new Footer1(new SalesTicket()))));
/*以下も、上記と同じ意味を持つ*/
//Component component;
//component = new SalesTicket();
//component = new Footer1(component);
//component = new Footer2(component);
//component = new Header2(component);
//component = new Header1(component);
//return component;
}
/// <summary>
/// ヘッダ1
/// 内約
/// フッタ1
/// フッタ2
/// を印字する
/// </summary>
/// <returns>印字に必要なオブジェクト群</returns>
public Component GetComponent2()
{
return new Header1(new Footer2(new Footer1(new SalesTicket())));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment