실례 분석 Ruby 디자인 모드 프로 그래 밍 에서 Strategy 정책 모드 의 사용
그 는 당신 에 게 현재 당신들 프로젝트 의 데이터베이스 에 사용자 정보 표 가 한 장 있 는데,안에 매우 많은 사용자 의 데이터 가 저장 되 어 있 으 며,지금 은 사용자 정 보 를 선택적으로 조회 하 는 기능 을 완성 해 야 한다 고 말 했다.그 는 많은 사용자 이름 을 포함 하 는 배열 을 전달 할 것 이 라 고 말 했다.이 사용자 이름 에 따라 해당 하 는 데 이 터 를 모두 찾 아야 한다.
이 기능 은 매우 간단 하 잖 아,너 는 시원스럽게 승낙 했 잖 아.프로젝트 가 MySQL 데이터 베 이 스 를 사용 하기 때문에 다음 코드 를 빠르게 썼 습 니 다.
require 'mysql'
class QueryUtil
def find_user_info usernames
@db = Mysql.real_connect("localhost","root","123456","test",3306);
sql = "select * from user_info where "
usernames.each do |user|
sql << "username = '"
sql << user
sql << "' or "
end
puts sql
result = @db.query(sql);
result.each_hash do |row|
#
end
# ,
ensure
@db.close
end
end
들 어 오 는 사용자 이름 배열 에 따라 SQL 문 구 를 조합 한 다음 데이터베이스 에 해당 하 는 줄 을 찾 습 니 다.디 버 깅 을 위해 서 는 맞 춤 형 SQL 문 구 를 인쇄 했다.그리고 이 방법 을 테스트 하기 위해 다음 코드 를 썼 습 니 다.
qUtil = QueryUtil.new
qUtil.find_user_info ["Tom", "Jim", "Anna"]
지금 테스트 코드 를 실행 해 보 세 요.프로그램 이 잘못 되 었 습 니 다.그래서 바로 인쇄 된 SQL 문 구 를 검 사 했 는데 과연 문 제 를 발견 했다.select * from user_info where username = 'Tom' or username = 'Jim' or username = 'Anna' or
맞 춤 형 SQL 문 구 는 마지막 에 or 키 워드 를 하나 더 추가 하 였 습 니 다!for 순환 이 마지막 데이터 까지 실 행 될 때 or 를 추가 해 서 는 안 되 지만 코드 가 어리석게 마지막 데이터 에 or 키 워드 를 추가 하여 SQL 구문 문법 이 잘못 되 었 습 니 다.
이거 어 떡 하지?
있다!너 는 영광 이 번쩍 이 며 해결 방법 을 생각해 냈 다.SQL 문 구 를 조합 한 후에 마지막 or 이전의 위 치 를 캡 처 하면 되 지 않 겠 습 니까?그래서 당신 은 코드 를 다음 과 같이 바 꾸 었 습 니 다.
require 'mysql'
class QueryUtil
def find_user_info usernames
@db = Mysql.real_connect("localhost","root","123456","test",3306);
sql = "select * from user_info where "
usernames.each do |user|
sql << "username = '"
sql << user
sql << "' or "
end
sql = sql[0 .. -" or ".length]
puts sql
result = @db.query(sql);
result.each_hash do |row|
#
end
# ,
ensure
@db.close
end
end
String 의 하위 문자열 을 자 르 는 방법 을 사용 하여 마지막 or 이전 부분 만 가 져 옵 니 다.이렇게 테스트 코드 를 실행 하면 모든 것 이 정상 입 니 다.인쇄 된 SQL 문 구 는 다음 과 같 습 니 다.
select * from user_info where username = 'Tom' or username = 'Jim' or username = 'Anna'
자,완공!너 는 자신만만 하 다.너의 leader 가 회 의 를 마치 고 와 서 너의 성 과 를 보 았 다.전체적으로 말 하면 그 는 매우 만 족 스 럽 지만 네가 사용 하 는 SQL 구문 조합 알고리즘 에 대해 그 는 항상 뭔 가 이상 하 다 고 느 꼈 지만 어디 가 나 쁜 지 말 할 수 없다.그래서 그 는 SQL 문 구 를 맞 추 는 또 다른 알고리즘 을 알려 주 었 다.코드 에 넣 으 라 고 했 지만 그 전의 알고리즘 도 삭제 하지 말고 남 겨 두 었 다가 다시 이야기 하 자 그 는 또 바 쁜 듯 이 달 아 났 다.그래서 당신 은 그 가 방금 가르쳐 준 알고리즘 을 넣 었 습 니 다.코드 는 다음 과 같 습 니 다.
require 'mysql'
class QueryUtil
def find_user_info(usernames, strategy)
@db = Mysql.real_connect("localhost","root","123456","test",3306);
sql = "select * from user_info where "
if strategy == 1
usernames.each do |user|
sql << "username = '"
sql << user
sql << "' or "
end
sql = sql[0 .. -" or ".length]
elsif strategy == 2
need_or = false
usernames.each do |user|
sql << " or " if need_or
sql << "username = '"
sql << user
sql << "'"
need_or = true
end
end
puts sql
result = @db.query(sql);
result.each_hash do |row|
#
end
# ,
ensure
@db.close
end
end
leader 가 가르쳐 준 맞 춤 법 을 볼 수 있 습 니 다.하나의 불 변 수 를 사용 하여 or 라 는 키 워드 를 추가 해 야 하 는 지 여 부 를 제어 합 니 다.처음으로 for 순환 을 실 행 했 을 때 이 불 값 은 false 이기 때문에 or 를 추가 하지 않 습 니 다.순환 의 마지막 에 불 값 을 true 로 할당 하면 나중에 순환 할 때마다 머리 에 or 키 워드 를 추가 합 니 다.머리 에 or 를 추가 하 는 방법 을 사 용 했 기 때문에 SQL 문장의 끝 에 or 가 하나 더 나 올 까 봐 걱정 하지 않 아 도 됩 니 다.그리고 당신 은 두 알고리즘 을 모두 보존 하기 위해 finduser_info 방법 에 매개 변 수 를 추가 하 였 습 니 다.strategy 값 은 1 로 첫 번 째 알고리즘 을 사용 하고 strategy 값 은 2 로 두 번 째 알고리즘 을 사용 하 는 것 을 표시 합 니 다.이렇게 테스트 코드 도 다음 과 같은 방식 으로 바 꿔 야 한다.
qUtil = QueryUtil.new
qUtil.find_user_info(["Tom", "Jim", "Anna"], 2)
여기 서 두 번 째 알고리즘 을 사용 하여 SQL 문 구 를 조합 하 는 것 을 매개 변 수 를 통 해 밝 혔 습 니 다.인쇄 결 과 는 첫 번 째 알고리즘 을 사용 하 는 것 과 똑 같 습 니 다.너 는 즉시 너의 leader 를 바 쁜 와 중 에 끌 고 와 서 그 에 게 너의 현재 성 과 를 검증 하 게 하 였 으 나,그 는 여전히 예전 과 같이 까다롭다.
"이렇게 쓰 면 finduser_info 이 방법의 논 리 는 너무 복잡 합 니 다.읽 기 에 매우 불리 하고 미래의 확장 에 도 불리 합 니 다.만약 에 제 가 세 번 째 네 번 째 알고리즘 을 추가 하고 싶다 면 이 방법 을 볼 수 있 습 니까?" 당신 의 leader 는 이러한 상황 에 직면 하면 전략 모델 로 해결 해 야 한다 고 지적 합 니 다.전략 모델 의 핵심 사상 은 바로 알고리즘 을 추출 하여 독립 된 대상 에 두 는 것 입 니 다.
너 를 지적 하기 위해 서 그 는 자신의 바 쁜 일 에 도 불구 하고 전략 모델 을 어떻게 사용 하여 최적화 하 는 지 가르쳐 주기 시작 했다.
먼저 부모 클래스 를 정의 합 니 다.부모 클래스 에는 get 이 포함 되 어 있 습 니 다.sql 방법,이 방법 은 간단하게 이상 을 던 지 는 것 입 니 다.
class Strategy
def get_sql usernames
raise "You should override this method in subclass."
end
end
그 다음 에 두 개의 하위 클래스 가 상기 부모 클래스 를 계승 하고 두 가지 SQL 문 구 를 조합 하 는 알고리즘 을 각각 두 개의 하위 클래스 에 추가 하도록 정의 합 니 다.
class Strategy1
def get_sql usernames
sql = "select * from user_info where "
usernames.each do |user|
sql << "username = '"
sql << user
sql << "' or "
end
sql = sql[0 .. -" or ".length]
end
end
class Strategy2
def get_sql usernames
sql = "select * from user_info where "
need_or = false
usernames.each do |user|
sql << " or " if need_or
sql << "username = '"
sql << user
sql << "'"
need_or = true
end
end
end
그리고 Query Util 에 있 는 finduser_info 방법 에서 Strategy 의 get 호출sql 방법 은 맞 춤 형 SQL 문 구 를 얻 을 수 있 습 니 다.코드 는 다음 과 같 습 니 다.
require 'mysql'
class QueryUtil
def find_user_info(usernames, strategy)
@db = Mysql.real_connect("localhost","root","123456","test",3306);
sql = strategy.get_sql(usernames)
puts sql
result = @db.query(sql);
result.each_hash do |row|
#
end
# ,
ensure
@db.close
end
end
마지막 으로 테스트 코드 는 find 를 호출 합 니 다.user_info 방법 은 어떤 정책 대상 을 사용 해 야 하 는 지 표시 하기 만 하면 됩 니 다.
qUtil = QueryUtil.new
qUtil.find_user_info(["Tom", "Jim", "Anna"], Strategy1.new)
qUtil.find_user_info(["Jac", "Joe", "Rose"], Strategy2.new)
출력 된 SQL 문 구 는 예상 치 못 했 습 니 다.다음 과 같 습 니 다.
select * from user_info where username = 'Tom' or username = 'Jim' or username = 'Anna'
select * from user_info where username = 'Jac' or username = 'Joe' or username = 'Rose'
정책 모드 를 수정 한 후에 코드 의 가 독성 과 확장 성 이 크게 향상 되 었 습 니 다.나중에 새로운 알고리즘 을 추가 해 야 하 더 라 도 손 쉽게 잡 을 수 있 습 니 다!전략 모드 와 간단 한 공장 모드 가 결 합 된 실례
필요:
백화점 의 수금 소프트웨어 는 고객 이 물건 을 구 매 하 는 단가 와 수량 에 따라 비용 을 계산 하면 판 촉 활동,20%할인,만 300 에서 100%할인 등 이 있 을 것 이다.
1.공장 모드 사용
# -*- encoding: utf-8 -*-
#
class CashSuper
def accept_cash(money)
end
end
#
class CashNormal < CashSuper
def accept_cash(money)
money
end
end
#
class CashRebate < CashSuper
attr_accessor :mony_rebate
def initialize(mony_rebate)
@mony_rebate = mony_rebate
end
def accept_cash(money)
money * mony_rebate
end
end
#
class CashReturn < CashSuper
attr_accessor :mony_condition, :mony_return
def initialize(mony_condition, mony_return)
@mony_condition = mony_condition
@mony_return = mony_return
end
def accept_cash(money)
if money > mony_condition
money - (money/mony_condition) * mony_return
end
end
end
#
class CashFactory
def self.create_cash_accept(type)
case type
when ' '
CashNormal.new()
when ' 8 '
CashRebate.new(0.8)
when ' 100'
CashReturn.new(300,100)
end
end
end
cash0 = CashFactory.create_cash_accept(' ')
p cash0.accept_cash(700)
cash1 = CashFactory.create_cash_accept(' 8 ')
p cash1.accept_cash(700)
cash2 = CashFactory.create_cash_accept(' 100')
p cash2.accept_cash(700)
사용자 정의 할인 비율 과 만 감 수량 을 만 들 었 습 니 다.존재 하 는 문제:
활동 의 종 류 를 늘 릴 때 는 50%를 할인 하고 500%를 채 우 면 200%를 줄 이 며 공장 류 에 분기 구 조 를 추가 해 야 한다.
이벤트 가 다양 하고 포인트 이벤트 가 늘 어 날 수도 있 습 니 다.100 포 인 트 를 채 우 고 10 포 인 트 를 더 하면 포 인 트 는 이벤트 상품 을 꼭 받 을 수 있 습 니 다.이때 하위 클래스 를 추가 해 야 합 니 다.
그러나 활동 을 늘 릴 때마다 공장 류 를 수정 하 는 것 은 나 쁜 처리 방식 이 므 로 알고리즘 이 바 뀌 었 을 때 더 좋 은 방법 이 있어 야 한다.
2.전략 모드
CashSuper 와 하위 클래스 는 변 하지 않 습 니 다.다음 내용 을 추가 합 니 다.
class CashContext
attr_accessor :cs
def initialize(c_super)
@cs = c_super
end
def result(money)
cs.accept_cash(money)
end
end
type = ' 8 '
cs=case type
when ' '
CashContext.new(CashNormal.new())
when ' 8 '
CashContext.new(CashRebate.new(0.8))
when ' 100'
CashContext.new(CashReturn.new(300,100))
end
p cs.result(700)
CashContext 류 는 서로 다른 CashSuper 서브 클래스 를 봉인 하여 해당 하 는 result 로 되 돌려 줍 니 다.알고리즘 이 어떻게 변 하 든 서로 다른 알고리즘 을 봉인 한 것 이다.result 로 결 과 를 얻 을 수 있 습 니 다.그러나 사용자 가 어떤 알고리즘 을 사용 할 지 판단 해 야 하 는 문제 가 있다.단순 공장 류 와 결합 할 수 있다.
3.전략 과 단순 공장 의 결합
class CashContext
attr_accessor :cs
def initialize(type)
case type
when ' '
@cs = CashNormal.new()
when ' 8 '
@cs = CashRebate.new(0.8)
when ' 100'
@cs = CashReturn.new(300,100)
end
end
def result(money)
cs.accept_cash(money)
end
end
cs=CashContext.new(' 8 ')
p cs.result(700)
CashContext 에서 서로 다른 하위 클래스 를 예화 하 였 습 니 다.(단순 공장하위 클래스 선택 과정 을 내부 로 옮 겨 알고리즘(전략 모드)을 패키지 합 니 다.
호출 자 는 더 간단 하고 매개 변수(활동 유형,원가)를 입력 하면 최종 결 과 를 얻 을 수 있 습 니 다.
여기 서 사용 자 는 한 가지 유형(Cash Context)만 알 면 되 고 간단 한 공장 에 서 는 두 가지 유형(Cash Factory 의 acceptcash 방법 과 Cash Factory),즉 더 철저하게 봉 인 된 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Ruby의 단일 메소드 및 단일 클래스 상세 정보단일 방법 Ruby는 단일 객체에만 적용되는 단일 객체 추가 방법을 단일 방법이라고 합니다. 또한 위에서 사용한 정의 방법 외에 Object#define_를 통해singleton_method 방법으로 단일 방법 정의...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.