第二十二章 手机软件何时统一--桥接模式(读书笔记)

第22章 手机软件何时统一--桥接模式

22.1 凭什么你的游戏我不能玩
 其实手机真正的发展也就近十年,此期间各大手机厂商都发展自己的软件部门开发手机软件,哪怕是同一品牌的手机,不同型号的也完全有可能软件不兼容。型号不同,软件还算是基本兼容,可惜不同品牌,软件基本还是不能整合在一起。

22.2 紧耦合的程序演化
  手机游戏类,M品牌手机游戏和N品牌手机游戏
  由于手机都需要通讯录功能,于是N品牌和M品牌都增加了通讯录的增删改查功能。
 第二十二章 手机软件何时统一--桥接模式(读书笔记)_第1张图片
 在很多情况下用继承会带来麻烦。比如对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
 在面向对象中有一个很重要的设计原则,那就是合成/聚合复用原则。即优先使用对象合成/聚合,而不是类的继承。

22.3 合成/聚合复用原则
 聚合是一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分,合成则是一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
 合成/聚合复用原则的好处是。优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
 按照上面的例子说就是需要学会用对象的职责,而不是结构来考虑问题,其实答案就在上面说到的手机和PC电脑的差别上。手机是不同的品牌公司,各自做自己的软件,这样就和22.2种的代码设计一样了。

22.4 松耦合的程序
 手机品牌类
 品牌N品牌M具体类

#pragma once
#include "handsetsoft.h"

class HandsetBrand
{
public:
	void SetHandsetSoft(HandSetSoft* p)
	{
		m_Soft = p;
	};

	virtual void Run(void) = 0;

	virtual ~HandsetBrand()
	{
		delete m_Soft;
	};
protected:
	HandSetSoft* m_Soft;
};

//N Brand
class HandsetBrandN :public HandsetBrand
{
public:
	void Run(void)
	{
		m_Soft->Run();
	};
};

//M Brand
class HandsetBrandM :public HandsetBrand
{
public:
	void Run(void)
	{
		m_Soft->Run();
	};
};

//new add
//S Brand
class HandsetBrandS :public HandsetBrand
{
public:
	void Run(void)
	{
		m_Soft->Run();
	};
};

手机软件 ,游戏,通讯录等具体类

#pragma once
#include <iostream>

//Mobile Soft
class HandSetSoft
{
public:
	virtual void Run(void) = 0;
	virtual ~HandSetSoft(){};
};

class HandSetGame : public HandSetSoft
{
public:
	void Run(void)
	{
		std::cout << "Mobile Game is Starting..." << std::endl;
	};
};

class HandSetAddressList : public HandSetSoft
{
public:
	void Run(void)
	{
		std::cout << "Mobile AddressList is Starting..." << std::endl;
	};
};

// new add
//MP3
class HandSetMP3 : public HandSetSoft
{
public:
	void Run(void)
	{
		std::cout << "Mobile MP3 is Starting..." << std::endl;
	};
};

客户端

#include "stdafx.h"
#include "HandsetBrand.h"

int _tmain(int argc, _TCHAR* argv[])
{
	HandsetBrand* ab = new HandsetBrandN();

	ab->SetHandsetSoft(new HandSetGame());
	ab->Run();

	ab->SetHandsetSoft(new HandSetAddressList());
	ab->Run();

	HandsetBrand* pm = new HandsetBrandM();

	pm->SetHandsetSoft(new HandSetGame());
	pm->Run();

	pm->SetHandsetSoft(new HandSetAddressList());
	pm->Run();

	delete pm;
	delete ab;
	return 0;
}

第二十二章 手机软件何时统一--桥接模式(读书笔记)_第2张图片 

现在如果要增加一个功能,比如MP3音乐播放功能,那么只要增加这个类就行了。不会影响其他任何类。 继承是一种强耦合的结构。父类变,子类就必须要变。所以我们在用继承时一定要在是“is-a”的关系时再考虑使用,而不是任何时候都去使用。

22.5 桥接模式
 将抽象部分与它的实现部分分离,使他们都可以独立地变化。如图22.4所示两个抽象类之间连接一根聚合线,所以我们形象地叫他是桥接模式。桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化。这就使得每一种变化不会影响到其他实现,从而达到应对变化的目的。

22.6 桥接模式基本代码

 第二十二章 手机软件何时统一--桥接模式(读书笔记)_第3张图片
 Implementor类,ConcreteImplementorA和ConcreteImplementorB等派生类

#pragma once
#include <iostream>

class Implementor
{
public:
	virtual void Operation(void) = 0;
};

class ConcreteImplementorA : public Implementor
{
public:
	void Operation(void)
	{
		std::cout << "ConcreteImplementorA..." << std::endl;
	};
};

class ConcreteImplementorB : public Implementor
{
public:
	void Operation(void)
	{
		std::cout << "ConcreteImplementorB..." << std::endl;
	};
};

Abstraction类,RefinedAbstrcation类

#pragma once
#include "Implementor.h"

class Abstraction
{
public:
	void SetImplementor(Implementor* p)
	{
		m_Impl = p;
	};
	
	virtual void DoOperation(void)
	{
		m_Impl->Operation();
	}

	virtual ~Abstraction()
	{
		delete m_Impl;
	};
protected:
	Implementor* m_Impl;
};

class RefinedAbstraction : public Abstraction
{
public:
	void DoOperation(void)
	{
		m_Impl->Operation();
	}
};
#include "abstraction.h"

int _tmain(int argc, _TCHAR* argv[])
{
	RefinedAbstraction* ab = new RefinedAbstraction();
	ab->SetImplementor(new ConcreteImplementorA());
	ab->DoOperation();

	ab->SetImplementor(new ConcreteImplementorB());
	ab->DoOperation();
	
	delete ab;
	return 0;
}

桥接模式强调的是将抽象部分和实现部分分离。说得通俗点就是实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少他们之间的耦合。

 

你可能感兴趣的:(第二十二章 手机软件何时统一--桥接模式(读书笔记))