SOLID

★SOLIDはオブジェクト指向による設計原則をまとめる。

S:Single Responsibility Principle 单一职责

O:Open-Closed Principle 开放封闭

L:Liskov Substitution Principle 里氏替换

I:Interface Segregation Principle 接口分离

D:Dependency Injection/Inversion Principle 依赖倒置

★SOLID以外

DRY (Don't Repeat Yourself)

Encapsulate what varies

Favour Composition over Inheritance

Programming for Interface not Implementation

Delegation Principle

・「SRP」に関するサンプル

改善前

class Employee

{

private string name;

private int id;

private double salary;

public Employee(string name, int id, double salary)

{

this.name = name;

this.id = id;

this.salary = salary;

}

public double CalculateSalary()

{

//implementation

}

public void Save(FileStream fs)

{

//implementation

}

public void Load(FileStream fs)

{

//implementation

}

}

・「OCP」に関するサンプル

改善前

enum AccountType

{

SAVINGS,

FIXEDDEPOSIT,

SALARY

}

class AccountInfo

{

public string Name { get; set; }

public string Address { get; set; }

public int AccountNo { get; set; }

}

class Account

{

private AccountInfo info;

private AccountType type;

private double balance;

public Account(double balance, AccountType type)

{

this.balance = balance;

this.type = type;

}

public void Withdraw(double amount)

{

this.balance -= amount;

}

public void Deposit(double amount)

{

this.balance += amount;

}

public void CalculateInterest()

{

switch (this.type)

{

case AccountType.SAVINGS:

//implementation

break;

case AccountType.FIXEDDEPOSIT:

//implementation

break;

case AccountType.SALARY:

//implementation

break;

default:

break;

}//switch

}

}

改善前

class Switcher {

private $fan;

function __construct() {

$this->fan = new Fan();

}

function turnOn() {

$this->fan->on();

}

function turnOff() {

$this->fan->off();

}

}

・「LSP」に関するサンプル

改善前

abstract class Widget

{

public abstract void SetText();

public abstract string GetText();

}

class Button : Widget

{

public override void SetText()

{

//implementation

}

public override string GetText()

{

//implementation

}

}

class ListBox : Widget

{

public override void SetText()

{

//implementation

}

public override string GetText()

{

//implementation

}

public string[] GetTextArray()

{

//implementation

}

}

class Dialog

{

public void GetCaption(Widget widget)

{

string str = widget.GetText();

ListBox listbox = widget as ListBox;

if (listbox != null)

{

string[] selectItems = listbox.GetTextArray();

//implementation

}

else

{

//implementation

}

}

}

・「ISP」に関するサンプル

改善前

interface IFile

{

void Open();

void Close();

void Read();

void Write();

void Seek();

void Position();

}

class TextFile : IFile

{

#region IFile Members

public void Open()

{

//implementation

}

public void Close()

{

//implementation

}

public void Read()

{

//implementation

}

public void Write()

{

//implementation

}

public void Seek()

{

//implementation

}

public void Position()

{

//implementation

}

#endregion

}

class SocketFile : IFile

{

#region IFile Members

public void Open()

{

//implementation

}

public void Close()

{

//implementation

}

public void Read()

{

//implementation

}

public void Write()

{

//implementation

}

public void Seek()

{

throw new NotImplementedException();

}

public void Position()

{

throw new NotImplementedException();

}

#endregion

}

改善前

interface Broker {

function buy($symbol, $volume);

function sell($symbol, $volume);

function dailyLosses($date);

function dailyEarnings($date);

}

class TOPIXBroker implements Broker {

public function buy($symbol, $volume) {

...

}

public function sell($symbol, $volume) {

...

}

public function dailyLosses($date) {

...

}

public function dailyEarnings($date) {

...

}

}

class StockMarket {

private $broker;

function __construct(Broker $broker) {

$this->broker = $broker;

}

function buyStocks() {

$this->broker->buy($data['sybmol'], $data['volume']);

}

function sellStocks() {

$this->broker->sell($data['sybmol'], $data['volume']);

}

}

class DailyReporter {

private $broker;

function __construct(Broker $broker) {

$this->broker = $broker;

}

function currentBalance() {

echo 'Today: ' . date(time()) . "\n";

echo 'Earnings: ' . $this->broker->dailyEarnings(time()) . "\n";

echo 'Losses: ' . $this->broker->dailyLosses(time()) . "\n";

}

}

・「DIP」に関するサンプル

改善前

class Lamp

{

public void TurnOn()

{

//implementation

}

public void TurnOff()

{

//implementation

}

}

class Button

{

private Lamp lamp = new Lamp();

private bool pressed = false;

public void Press()

{

if (this.pressed)

{

this.lamp.TurnOff();

}

else

{

this.lamp.TurnOn();

this.pressed = true;

}//if

}

}

改善後

class Employee

{

private string name;

private int id;

private double salary;

public Employee(string name, int id, double salary)

{

this.name = name;

this.id = id;

this.salary = salary;

}

public double CalculateSalary()

{

//implementation

}

}

class Db

{

public void Save(Employee emp)

{

//implementation

}

public void Load(Employee emp)

{

//implementation

}

}

改善後

class AccountInfo

{

public string Name { get; set; }

public string Address { get; set; }

public int AccountNo { get; set; }

}

abstract class Account

{

protected AccountInfo info;

protected double balance;

public Account(double balance)

{

this.balance = balance;

}

public void Withdraw(double amount)

{

this.balance -= amount;

}

public void Deposit(double amount)

{

this.balance += amount;

}

public abstract void CalculateInterest();

}

class Savings : Account

{

public Savings(double balance) : base(balance) { }

public override void CalculateInterest()

{

//implementation

}

}

class FixedDeposit : Account

{

public FixedDeposit(double balance) : base(balance) { }

public override void CalculateInterest()

{

//implementation

}

}

class Salary : Account

{

public Salary(double balance) : base(balance) { }

public override void CalculateInterest()

{

//implementation

}

}

改善後

interface Switchable {

function on();

function off();

}

class Fan implements Switchable {

public function on() {

...

}

public function off() {

...

}

}

class Switcher {

private $switchable;

function __construct(Switchable $switchable) {

$this->switchable = $switchable;

}

function turnOn() {

$this->switchable->on();

}

function turnOff() {

$this->switchable->off();

}

}

$fan = new Fan();

$switch = new Switcher($fan);

$switch->turnOn();

$switch->turnOff();

改善後

abstract class Widget

{

public abstract void SetText();

public abstract string GetText();

}

class Button : Widget

{

public override void SetText()

{

//implementation

}

public override string GetText()

{

//implementation

}

}

class ListBox : Widget

{

public override void SetText()

{

//implementation

}

public override string GetText()

{

//implementation

}

public string[] GetTextArray()

{

//implementation

}

}

class Dialog

{

public void GetCaption(Widget widget)

{

string str = widget.GetText();

//implementation

}

}

class ListBoxDialog : Dialog

{

public void GetCaption(ListBox listbox)

{

base.GetCaption(listbox);

string[] selectItems = listbox.GetTextArray();

//implementation

}

}

改善後

interface IFile

{

void Open();

void Close();

void Read();

void Write();

}

interface IDiskFile : IFile

{

void Seek();

void Position();

}

class TextFile : IDiskFile

{

#region IFile Members

public void Open()

{

//implementation

}

public void Close()

{

//implementation

}

public void Read()

{

//implementation

}

public void Write()

{

//implementation

}

public void Seek()

{

//implementation

}

public void Position()

{

//implementation

}

#endregion

}

class SocketFile : IFile

{

#region IFile Members

public void Open()

{

//implementation

}

public void Close()

{

//implementation

}

public void Read()

{

//implementation

}

public void Write()

{

//implementation

}

#endregion

}

改善後

interface BrokerTransactions {

function buy($symbol, $volume);

function sell($symbol, $volume);

}

interface BrokerStatistics {

function dailyLosses($date);

function dailyEarnings($date);

}

class TOPIXBroker implements BrokerTransactions, BrokerStatistics {

public function buy($symbol, $volume) {

...

}

public function sell($symbol, $volume) {

...

}

public function dailyLosses($date) {

...

}

public function dailyEarnings($date) {

...

}

}

class StockMarket {

private $broker;

function __construct(BrokerTransactions $broker) {

$this->broker = $broker;

}

function buyStocks() {

$this->broker->buy($data['sybmol'], $data['volume']);

}

function sellStocks() {

$this->broker->sell($data['sybmol'], $data['volume']);

}

}

class DailyReporter {

private $broker;

function __construct(BrokerStatistics $broker) {

$this->broker = $broker;

}

function currentBalance() {

echo 'Today: ' . date(time()) . "\n";

echo 'Earnings: ' . $this->broker->dailyEarnings(time()) . "\n";

echo 'Losses: ' . $this->broker->dailyLosses(time()) . "\n";

}

}

改善後

interface ISwitch

{

void TurnOn();

void TurnOff();

}

class Lamp : ISwitch

{

#region ISwitch Members

public void TurnOn()

{

//implementation

}

public void TurnOff()

{

//implementation

}

#endregion

}

class Button

{

private ISwitch iSwitch;

private bool pressed = false;

public void SetSwitch(ISwitch s)

{

this.iSwitch = s;

}

public void Press()

{

if (this.pressed)

{

this.iSwitch.TurnOff();

}

else

{

this.iSwitch.TurnOn();

this.pressed = true;

}//if

}

}