2年生デザインモード構造パレット


Adapter


  • クラスのインタフェースをユーザが望む他のインタフェースのモードに変換し、互換性のないインタフェースのために一緒に動作できないクラスを一緒に動作させる




  • UML


  • Target class(existing system)
  • クライアントは
  • を使用しています.
  • 要求()インタフェース
  • がある.

  • Adaptee class(additional system)
  • specificRequest()

  • Adapter class
  • Targetclass->その他のサービス
  • を変更する必要はありません.
  • ターゲット、Adapteeを継承し、2種類の情報
  • を得ることができる.

  • client -> Adapter(Request) -> Adaptee(SpecificReqest)

  • C++のみ複数継承可能
  • #include<iostream>
    #include<string>
    using namespace std;
    
    class Target {
    public:
    	virtual void Request() {
    		cout << "Existing Service" << endl;
    	}
    };
    
    class Adaptee {
    public:
    	void SpecificRequest() {
    		cout << "Added Service" << endl;
    	}
    };
    
    class Adapter : public Target {
    private:
    	Adaptee* adaptee_;
    public:
    	Adapter(Adaptee* adaptee) : adaptee_(adaptee) {}
    	void Request() {
    		this->adaptee_->SpecificRequest();
    	}
    };
    
    int main() {
    	Target* target = new Target;
    	target->Request();
    	Adaptee* adaptee = new Adaptee;
    	Adapter* adapter = new Adapter(adaptee);
    	adapter->Request();
    	return 0;
    }
  • の利点:単一の責任原則で、既存のカテゴリを変更することなく他の機能
  • を追加できます.
    欠点:追加のサービスレベルが多ければ多いほど複雑になります.
    ->主に既存のclassが十分に大きく、変更が困難な場合に使用される

    Bridge


  • 実装部分から抽象層を離れ,それぞれ独立して変形させるモード




  • type1 : existing class

  • 継承を使用しない

  • UML


  • 抽象クラスとImplementorクラスは相互継承の関係ではありません
  • #include<iostream>
    #include<string>
    using namespace std;
    
    class Implementation {
    public:
    	virtual void print() = 0;
    };
    
    class Abstraction {
    protected:
    	Implementation* implementation_;
    public:
    	Abstraction(Implementation* implementation) : implementation_(implementation) { }
    	virtual void Operation() {
    		cout << "Caffeine: ";
    		this->implementation_->print();
    	}
    };
    
    class ExtendedAbstraction : public Abstraction {
    public:
    	ExtendedAbstraction(Implementation* implementation) : Abstraction(implementation) { }
    	void Operation() {
    		cout << "Decaf: ";
    		this->implementation_->print();
    	}
    };
    
    class ConcreteImplementationA : public Implementation {
    public:
    	void print() {
    		cout << "Hot" << endl;
    	}
    };
    
    class ConcreteImplementationB : public Implementation {
    public:
    	void print() {
    		cout << "Iced" << endl;
    	}
    };
    
    int main() {
    	Implementation* implementation = new ConcreteImplementationA;
    	Abstraction* abstraction = new Abstraction(implementation);
    	abstraction->Operation();
    
    	implementation = new ConcreteImplementationB;
    	abstraction = new ExtendedAbstraction(implementation);
    	abstraction->Operation();
    	return 0;
    }
  • 賛成:プラットフォーム(実装)-独立したクラスを作成できます.単一責任原則
  • 欠点:パターンを追加するとより複雑になる可能性があります
  • composite


  • オブジェクト間の関係をツリー構造に整理し、階層全体のパターンを部分的に表すことで、ユーザーが単一のオブジェクトと複合オブジェクトを同時に処理できるようにします.




  • 再帰モードを持つシェイプ

  • UML
    ![]( https://media.vlpt.us/images/sgh9702/post/ff26563f-a415-4f8e-ac85-afac16 419277/1.PNG)
  • #include<iostream>
    #include <list> 
    using namespace std;
    
    class Component {
    protected:
    	Component* parent_;
    public:
    	void SetParent(Component* parent) {
    		this->parent_ = parent;
    	}
    	Component* GetParent() const {
    		return this->parent_;
    	}
    	virtual void Add(Component* component) {}
    	virtual bool IsComposite() {
    		return false;
    	}
    	virtual string Operation() = 0;
    };
    
    class Leaf : public Component {
    public:
    	string Operation() {
    		return "Leaf";
    	}
    };
    
    class Composite : public Component {
    protected:
    	list<Component*> children_;
    public:
    	void Add(Component* component) {
    		this->children_.push_back(component);
    		component->SetParent(this);
    	}
    	bool IsComposite() {
    		return true;
    	}
    	string Operation() {
    		std::string result;
    		for (Component* c : children_) {
    			if (c == children_.back()) result += c->Operation();
    			else result += c->Operation() + "+";
    		}
    		return "Branch(" + result + ")";
    	}
    };
    
    int main() {
    	Component *c0 = new Composite;
    	Component* l1 = new Leaf;
    	Component* c1 = new Composite;
    
    	c0->Add(l1);
    	c0->Add(c1);
    
    	cout << c0->Operation() << endl;
    
    	return 0;
    }

    Decorator


  • 特定の状況と用途に応じて、オブジェクトに責任を追加するモードは、拡張機能が必要な場合にサブクラスを代替する柔軟な代替案となります.




  • UML


  • ConcreteComponent : basic object
  • #include<iostream>
    #include <list> 
    using namespace std;
    
    class Component {
    public:
    	virtual string Operation() = 0;
    };
    class ConcreteComponent : public Component {
    public:
    	string Operation() {
    		return "Coffee";
    	}
    };
    
    class Decorator : public Component {
    protected:
    	Component* component_;
    public:
    	Decorator(Component* component) : component_(component) { }
    	string Operation() {
    		return this->component_->Operation();
    	}
    };
    
    class ConcreteDecoratorA : public Decorator {
    public:
    	ConcreteDecoratorA(Component* component) : Decorator(component) { }
    	string Operation() {
    		return "syrup1 + ("	+ Decorator::Operation()+ ")";
    	}
    };
    
    class ConcreteDecoratorB : public Decorator {
    public:
    	ConcreteDecoratorB(Component* component) : Decorator(component) {
    	}
    	string Operation() {
    		return "syrup2 + ("	+ Decorator::Operation()+ ")";
    	}
    };
    
    int main() {
    	Component* coffee = new ConcreteComponent;
    	coffee = new ConcreteDecoratorA(coffee); //syrup1 added
    	coffee = new ConcreteDecoratorA(coffee); //syrup1 added
    	coffee = new ConcreteDecoratorB(coffee); //syrup2 added
    	coffee = new ConcreteDecoratorB(coffee); //syrup2 added
    	coffee = new ConcreteDecoratorB(coffee); //syrup2 added
    	cout << "RESULT: " << coffee->Operation();
    	return 0;
    }
    
  • の利点
  • 新しいサブクラスを作成することなくオブジェクトを拡張する動作
  • の実行時にオブジェクトに責任
  • を追加または削除できます.
  • オブジェクトを複数のラインストーンにマージできます.
  • 単一責任原則
  • の欠点
  • Rapperスタックから特定のRapperを削除するのは難しい.
  • decorator挙動はdecoratorスタックの順序に依存しないでdecoratorを実現することは困難である.
  • Facade


  • サブシステムを使いやすくする高度なインタフェースを定義します.




  • UML

  • #include<iostream>
    #include <list> 
    #include<string>
    using namespace std;
    
    class Subsystem1 {
    public:
    	string init() { return "Subsystem1: Init!\n"; }
    	string run() { return "Subsystem1: On!\n"; }
    };
    class Subsystem2 {
    public:
    	string init() { return "Subsystem2: Init!\n"; }
    	string run() { return "Subsystem2: On!\n"; }
    };
    
    class Facade{
    protected:
    	Subsystem1* subsystem1_;
    	Subsystem2* subsystem2_;
    public:
    	Facade(Subsystem1* subsystem1, Subsystem2* subsystem2) {
    		this->subsystem1_ = new Subsystem1();
    		this->subsystem2_ = new Subsystem2();
    	}
    	string Operation() {
    		string result = "Initializing subsystems:\n";
    		result += this->subsystem1_-> init();
    		result += this->subsystem2_-> init();
    		result += "Ready to use: \n";
    		result += this->subsystem1_->run();
    		result += this->subsystem2_->run();
    		return result;
    	}
    };
    
    int main() {
    	Subsystem1* subsystem1 = new Subsystem1;
    	Subsystem2* subsystem2 = new Subsystem2;
    	Facade* facade = new Facade(subsystem1, subsystem2);
    	cout << facade->Operation();
    	return 0;
    }
    利点:サブシステムの複雑さからコードを分離できる
    欠点:アプリケーションのすべてのクラスに結合されたgodオブジェクトです.

    Flyweight


  • 同じオブジェクトまたは類似オブジェクト間でできるだけ多くのデータを共有および使用することで、メモリ使用量を最小限に抑えるモード




  • UML

  • #include<iostream>
    #include <list> 
    #include<string>
    #include<unordered_map>
    using namespace std;
    
    struct SharedState
    {
    	string type_, color_;
    	SharedState(const string& type, const string& color)
    		: type_(type), color_(color) { }
    	friend ostream& operator<<(ostream& os, const SharedState& ss)
    	{
    		return os << "[ " << ss.type_ << " , " << ss.color_ << " ]";
    	}
    };
    struct UniqueState
    {
    	string price_;
    	UniqueState(const string& price) : price_(price) { }
    	friend ostream& operator<<(std::ostream& os, const UniqueState& us)
    	{
    		return os << "[ " << us.price_ << " ]";
    	}
    };
    
    class Flyweight
    {
    private:
    	SharedState* shared_state_;
    public:
    	Flyweight(const SharedState* shared_state) : shared_state_(new SharedState(*shared_state)) { }
    	Flyweight(const Flyweight& other) : shared_state_(new SharedState(*other.shared_state_)) { }
    	SharedState* shared_state() const { return shared_state_; }
    	void Operation(const UniqueState& unique_state) const
    	{
    		cout << "Flyweight: Displaying shared (" << *shared_state_
    			<< ") and unique (" << unique_state << ") state." << endl;
    	}
    };
    
    class FlyweightFactory
    {
    private:
    	unordered_map<string, Flyweight> flyweights_;
    	string GetKey(const SharedState& ss) const { return ss.type_ + "_" + ss.color_; }
    public:
    	FlyweightFactory(std::initializer_list<SharedState> share_states)
    	{
    		for (const SharedState& ss : share_states)
    			this->flyweights_.insert(make_pair<string, Flyweight>(this->GetKey(ss), Flyweight(&ss)));
    	}
    	Flyweight GetFlyweight(const SharedState& shared_state)
    	{
    		string key = this->GetKey(shared_state);
    		if (this->flyweights_.find(key) == this->flyweights_.end())
    			this->flyweights_.insert(make_pair(key, Flyweight(&shared_state)));
    		return this->flyweights_.at(key);
    	}
    	void ListFlyweights() const
    	{
    		size_t count = this->flyweights_.size();
    		for (pair<string, Flyweight> pair : this->flyweights_) cout << pair.first << "\n";
    	}
    };
    
    void AddItem(
    	FlyweightFactory& ff, const string& price,
    	const string& type, const string& color)
    {
    	cout << "Adding an item to DB." << endl;;
    	const Flyweight& flyweight = ff.GetFlyweight({ type, color });
    	flyweight.Operation({ price });
    }
    
    int main()
    {
    	FlyweightFactory* factory = new FlyweightFactory({ {"Americano", "black" }, { "Mocha", "white" } });
    	factory->ListFlyweights();
    	AddItem(*factory, "5000", "Americano", "black");
    	AddItem(*factory, "6000", "Mocha", "white");
    	AddItem(*factory, "4000", "Espresso", "black");
    	factory->ListFlyweights();
    	return 0;
    }
  • の利点:プログラムに類似のオブジェクトがたくさんあると仮定すると、メモリ
  • を大幅に節約できます.
    欠点:コードがより複雑になる

    Proxy


  • エージェントはクラスで、他のもののインタフェースを接続する役割を果たしています.




  • UML

  • #include<iostream>
    #include <list> 
    #include<string>
    using namespace std;
    
    class Subject {
    public:
    	virtual void Request() const = 0;
    };
    class RealSubject : public Subject {
    public:
    	void Request() const {
    		cout << "Handling Request." << endl;
    	}
    };
    
    class Proxy : public Subject {
    private:
    	RealSubject* real_subject_;
    	bool CheckAccess() const {
    		cout << "Proxy: Checking Access" << endl;
    		return true;
    	}
    public:
    	Proxy(RealSubject* real_subject) : real_subject_(new RealSubject(*real_subject)) { }
    	void Request() const override {
    		if (this->CheckAccess()) {
    			cout << "Proxy: Access Granted" << endl;
    			this->real_subject_->Request();
    		}
    	}
    };
    
    int main() {
    	RealSubject* real_subject = new RealSubject;
    	Proxy* proxy = new Proxy(real_subject);
    	proxy->Request();
    	return 0;
    }

  • 長所
  • クライアントは、知らないうちにサービスオブジェクト
  • を制御することができる.
  • サービスオブジェクトのライフサイクルを管理できます.

  • 短所
  • サービス応答は遅延する可能性があります.