Strateji Modelinin Gerçek Dünyadan Örneği


96

OCP müdürünü ve bunu başarmak için strateji modelini nasıl kullanacağımı okuyordum .

Bunu birkaç kişiye açıklamaya çalışacaktım, ancak aklıma gelen tek örnek, "sipariş" statüsünün ne olduğuna bağlı olarak farklı doğrulama sınıfları kullanmaktır.

İnternette birkaç makale okudum, ancak bunlar genellikle stratejiyi kullanmak için raporlar / faturalar / doğrulama vb. Gibi gerçek bir nedeni açıklamıyor ...

Bir strateji modelinin yaygın olduğunu düşündüğünüz gerçek dünya örnekleri var mı?

Yanıtlar:


100

Peki buna ne dersin:

Bir dosyayı şifrelemelisiniz.

Küçük dosyalar için, dosyanın tamamının okunduğu ve bellekte tutulduğu "bellekte" stratejisini kullanabilirsiniz (1 gb'den küçük dosyalar için diyelim)

Büyük dosyalar için, dosyanın bazı bölümlerinin bellekte okunduğu ve kısmi şifrelenmiş sonuçların tmp dosyalarında depolandığı başka bir strateji kullanabilirsiniz.

Bunlar, aynı görev için iki farklı strateji olabilir.

Müşteri kodu aynı görünecektir:

 File file = getFile();
 Cipher c = CipherFactory.getCipher( file.size() );
 c.performAction();



// implementations:
interface  Cipher  {
     public void performAction();
}

class InMemoryCipherStrategy implements Cipher { 
         public void performAction() {
             // load in byte[] ....
         }
}

class SwaptToDiskCipher implements Cipher { 
         public void performAction() {
             // swapt partial results to file.
         }

}

     Cipher c = CipherFactory.getCipher( file.size() );

Şifre için doğru strateji örneğini döndürür.

Umarım bu yardımcı olur.

(Cipher'ın doğru kelime olup olmadığını bile bilmiyorum: P)


8
Örneğiniz artık bir Fabrika Modeli değil mi? Ayrıca örneğin C # ile çalışmayacağını düşünüyorum. "GetCipher ()" yönteminiz statik bir yöntemdir, ancak C # 'da bir arabirim üzerinde statik bir yöntem tanımlayamazsınız (ne Java'da da düşünüyorum ama bunun için emin değilim).
FrenchData

10
Birlikte giderler. Fabrika, stratejiyi yaratır, ancak strateji, (temelde) aynı işlemi gerçekleştirmek için algoritmayı kendi kendine tutar. Strateji, çalışma zamanında da değiştirilebilir. Fabrika yöntemi konusunda haklısınız, onu değiştirdim.
OscarRyz

Osacars noktasını eklemek için, fabrika olmadan bu fabrika olmadan oluşturulabilir Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
Abhijit Mazumder

@FrenchData ile katılıyorum. Harika bir örnek olmakla birlikte, varlığı CipherFactoryStrateji modeline aşina olmayanların kafasını karıştırabilir.
user487772

1
Fabrika kalıbı yaratıcılıkla ilgilidir, Strateji ise Davranışsaldır. Biraz farklı değil mi?
nhoxbypass

62

Yine, eski bir gönderi, ancak yine de aramalarda çıkıyor, bu yüzden iki örnek daha ekleyeceğim (Kod C # içindedir). Strateji modelini, proje yöneticilerinin "Uygulamanın 'X' yapmasını istiyoruz, ancak 'X' henüz net değil ve yakın gelecekte değişebilir dediği zaman kıçımı kurtardığı için kesinlikle seviyorum. " Strateji modelini açıklayan bu videoda örnek olarak StarCraft kullanılmıştır.

Bu kategoriye giren şeyler:

  • Sıralama: Bu sayıları sıralamak istiyoruz, ancak BrickSort, BubbleSort veya başka bir sıralama kullanıp kullanmayacağımızı bilmiyoruz.

  • Doğrulama: Öğeleri "Bazı kurallara" göre kontrol etmemiz gerekiyor, ancak bu kuralın ne olacağı henüz net değil ve yenilerini düşünebiliriz.

  • Oyunlar: Oyuncunun hareket ettiğinde ya yürümesini ya da koşmasını istiyoruz, ama belki gelecekte yüzebilmesi, uçabilmesi, ışınlanabilmesi, yeraltına girebilmesi vb.

  • Bilgileri saklama: Uygulamanın bilgileri Veritabanına depolamasını istiyoruz, ancak daha sonra bir dosyayı kaydetmesi veya bir web araması yapması gerekebilir.

  • Çıktı alma: X'i düz bir dizge olarak çıkarmamız gerekir, ancak daha sonra bir CSV, XML, JSON vb. Olabilir.


Örnekler

Kullanıcıların bir veritabanındaki kişilere ürün atayabileceği bir projem var. Bir ürünün bir kişiye bu atanması, bazı iş kurallarına bağlı olarak "Onaylandı" veya "Reddedildi" durumuna sahiptir. Örneğin: bir kullanıcı belirli bir yaştaki bir kişiye bir ürün atarsa, durumu reddedilmelidir; Öğedeki iki alan arasındaki fark 50'den büyükse, durumu reddedilir vb.

Şimdi, geliştirme anında bu iş kuralları henüz tam olarak net değil ve her an yeni kurallar ortaya çıkabilir. Stragety modelinin gücü, IRules listesi verilen bir RuleAgent yapmamdır.

public interface IRule {
    bool IsApproved(Assignment assignment); 
 }

Bir kişiye bir ürün atama anında, bir RuleAgent oluşturuyorum, ona bir kurallar listesi veriyorum (hepsi IRule uyguluyor) ve ondan bir atamayı doğrulamasını istiyorum. Tüm kuralları üzerinden geçecek. Bu, hepsi aynı arayüzü uyguladıkları için, hepsi IsApprovedyönteme sahiptir ve herhangi biri yanlış döndürürse yanlış döndürür.

Şimdi, örneğin yönetici aniden gelip dediğinde, stajyerlere yapılan tüm atamaları veya fazla mesai yapan insanlara yapılan tüm görevleri de reddetmemiz gerekiyor ... Bunun gibi yeni sınıflar yaparsınız:

public OvertimeRule : IRule
{
    public bool IsApproved(Assignment assignment) //Interface method
    {
        if (assignment.Person.Timesheet >= 40)
        {
            return false;
        }
        return true;
    }
}

public InternRule : IRule
{
    public bool IsApproved(Assignment assignment) //Interface method
    {
        if (assignment.Person.Title == "Intern")
        {
            return false;
        }
        return true;
    }
}

İf ifadeleri veya kodu eklemeye veya kaldırmaya devam etmeniz gerekmediğini görüyorsunuz, sadece IRUle arayüzünü uygulayan yeni bir kural sınıfı oluşturun ve gerektiğinde bunları değiştirin.


Bir başka harika örnek: Scott Allen'ın http://www.asp.net/mvc/pluralsight adresindeki video serisi, burada uygulamanın Unit-test bölümünde strateji modelini kullanıyor

Popülerliğe göre öğeleri gösteren bir sayfası olan bir web sitesi kurar. Bununla birlikte, "Popüler" birçok şey olabilir (çoğu görüntüleme, çoğu abone, oluşturma tarihi, çoğu etkinlik, en az yorum miktarı vb.) Ve yönetimin henüz tam olarak nasıl sipariş vereceğini bilmemesi ve farklı deneyimler yapmak isteyebileceği durumlarda daha sonraki bir tarihte siparişler. Bir sipariş yöntemi ile bir arabirim (IOrderAlgorithm veya başka bir şey) oluşturursunuz ve bir Orderer nesnesinin sıralamayı IOrderAlgorithm arabiriminin somut bir uygulamasına devretmesine izin verirsiniz. Bir "Yorum Siparişi", "Etkinlik Siparişi" vb. Oluşturabilirsiniz. Ve yeni gereksinimler ortaya çıktığında bunları değiştirin.


Bunun biraz sorunun kapsamı dışında olduğunu biliyorum ama sonra ne olacak? Şimdi buna sahibiz InternRuleama nasıl tetikliyoruz OvertimeRule? OvertimeRule.IsApprovedŞimdi denen mantığın da çağırdığından nasıl emin olabiliriz InternRule.IsApproved?
Spencer Ruport

15

Önemli notlar:

  1. Strateji , davranışsal tasarım modelidir. Algoritma ailesi arasında geçiş yapmak için kullanılır.

  2. Bu model, bir soyut strateji arayüzü ve bu arayüzün birçok somut strateji uygulamasını ( algoritmaları ) içerir.

  3. Uygulama yalnızca strateji arayüzünü kullanır . Bazı yapılandırma parametrelerine bağlı olarak, somut strateji arayüze etiketlenecektir .

Wikipedia'dan UML Diyagramı

görüntü açıklamasını buraya girin

Gerçek bir kelime örneği: Bazı aylarda (Temmuz-Aralık) indirim sunan havayolları . Ay sayısına göre fiyatlandırma seçeneklerine karar veren bir Ücret modülünüz olabilir .

Basit bir örneğe bir göz atın. Bu örnek, özel günlerde / indirimli saatlerde alışveriş sepeti ürünlerinde kolayca indirim sağlayan çevrimiçi mağazacılık uygulamalarına genişletilebilir.

import java.util.*;

/* Interface for Strategy */
interface OfferStrategy {
    public String getName();
    public double getDiscountPercentage();
}
/* Concrete implementation of base Strategy */
class NoDiscountStrategy implements OfferStrategy{
    public String getName(){
        return this.getClass().getName();
    }
    public double getDiscountPercentage(){
        return 0;
    }
}
/* Concrete implementation of base Strategy */
class QuarterDiscountStrategy implements OfferStrategy{
    public String getName(){
        return this.getClass().getName();
    }
    public double getDiscountPercentage(){
        return 0.25;
    }
}
/* Context is optional. But if it is present, it acts as single point of contact
   for client. 

   Multiple uses of Context
   1. It can populate data to execute an operation of strategy
   2. It can take independent decision on Strategy creation. 
   3. In absence of Context, client should be aware of concrete strategies. Context acts a wrapper and hides internals
   4. Code re-factoring will become easy
*/
class StrategyContext {
    double price; // price for some item or air ticket etc.
    Map<String,OfferStrategy> strategyContext = new HashMap<String,OfferStrategy>();
    StrategyContext(double price){
        this.price= price;
        strategyContext.put(NoDiscountStrategy.class.getName(),new NoDiscountStrategy());
        strategyContext.put(QuarterDiscountStrategy.class.getName(),new QuarterDiscountStrategy());        
    }
    public void applyStrategy(OfferStrategy strategy){
        /* 
        Currently applyStrategy has simple implementation. You can use Context for populating some more information,
        which is required to call a particular operation            
        */
        System.out.println("Price before offer :"+price);
        double finalPrice = price - (price*strategy.getDiscountPercentage());
        System.out.println("Price after offer:"+finalPrice);
    }
    public OfferStrategy getStrategy(int monthNo){
        /*
            In absence of this Context method, client has to import relevant concrete Strategies everywhere.
            Context acts as single point of contact for the Client to get relevant Strategy
        */
        if ( monthNo < 6 )  {
            return strategyContext.get(NoDiscountStrategy.class.getName());
        }else{
            return strategyContext.get(QuarterDiscountStrategy.class.getName());
        }

    }
}
public class StrategyDemo{    
    public static void main(String args[]){
        StrategyContext context = new StrategyContext(100);
        System.out.println("Enter month number between 1 and 12");
        int month = Integer.parseInt(args[0]);
        System.out.println("Month ="+month);
        OfferStrategy strategy = context.getStrategy(month);
        context.applyStrategy(strategy);
    }

}

çıktı:

Enter month number between 1 and 12
Month =1
Price before offer :100.0
Price after offer:100.0

Enter month number between 1 and 12
Month =7
Price before offer :100.0
Price after offer:75.0

Yararlı makaleler:

dzone tarafından strateji modeli

kaynak oluşturmaya göre strateji modeli


teşekkürler .... çok mantıklı .... kabul etti applyStrategy () çok fazla kara büyü elde etmek için bir canavardır. Ayrıca, StrategyContext'te stratejileri tutmanın statik olmayan yolu birinci
sınıftır

12

Oldukça basit birkaç örnek düşünebilirim:

  • Bir listeyi sıralamak. Strateji, listedeki iki öğeden hangisinin "İlk" olduğuna karar vermek için kullanılan karşılaştırmadır
  • Çalışma zamanında sıralama algoritmasının kendisinin (QuickSort, HeapSort, vb.) Seçilebileceği bir uygulamanız olabilir.
  • Log4Net ve Log4j'de Ekler, Düzenler ve Filtreler
  • Kullanıcı Arabirimi araç setlerinde Yerleşim Yöneticileri
  • Veri sıkıştırma. Tek yöntemi aşağıdaki gibi görünen bir ICompressor arabiriminiz olabilir:

    bayt [] sıkıştır (bayt [] girişi);

    Somut sıkıştırma sınıflarınız RunLengthCompression, DeflateCompression vb. Şeyler olabilir.


9

Strateji modelinin yaygın bir kullanımı, özel sıralama stratejileri tanımlamaktır (daha yüksek dereceli işlevleri olmayan dillerde), örneğin Java'da dizelerin bir listesini uzunluğa göre sıralamak, anonim bir iç sınıfı geçirmek (strateji arayüzünün bir uygulaması):

List<String> names = Arrays.asList("Anne", "Joe", "Harry");
Collections.sort(names, new Comparator<String>() {
  public int compare(String o1, String o2) {
    return o1.length() - o2.length();
  }
});
Assert.assertEquals(Arrays.asList("Joe", "Anne", "Harry"), names);

Benzer şekilde, stratejiler nesne veri tabanları ile yerel sorgular için kullanılabilir, örneğin db4o'da:

List<Document> set = db.query(new Predicate<Document>() {
  public boolean match(Document candidate) {
    return candidate.getSource().contains(source);
  }
});

8

Kullanıcı tabanını her gün kurumsal dizinimizle senkronize eden bir uygulamam var. Kullanıcılar, Üniversite'deki durumlarına göre uygun veya uygun değiller. Sağlama programı her gün geçer ve uygun olması gerekenlerin uygulamada hazırlandığından ve olmayanların provizyonunun kaldırıldığından emin olur (aslında zarif bir bozulma algoritmasına göre, ancak bu işin dışında). Cumartesi günü, her kullanıcının bazı özelliklerini senkronize eden ve uygun uygunluğa sahip olduklarından emin olan daha kapsamlı bir güncelleme yapıyorum. Ayın sonunda, o ayın kullanımına bağlı olarak bir miktar geri ödeme işlemi yapıyorum.

Bu senkronizasyonu yapmak için birleştirilebilir bir strateji modeli kullanıyorum. Ana program, temel olarak haftanın gününe (yalnızca değişiklikleri senkronize et / tümünü senkronize et) ve akademik takvime göre dönem saatine bağlı olarak bir ana strateji seçer. Faturalandırma döngüsü sona eriyorsa, bunu bir faturalandırma stratejisiyle de oluşturur. Daha sonra seçilen stratejiyi standart bir arayüz aracılığıyla çalıştırır.

Bunun ne kadar yaygın olduğunu bilmiyorum ama strateji modeline mükemmel bir şekilde uyduğunu hissettim.


Bu çok güzel bir örnek. Ayrıca, size komut ve strateji modeli arasındaki farkı kısaca açık bir şekilde anlatır - niyet. "Ana program temelde haftanın gününe bağlı olarak bir ana strateji seçer "
Utsav T

7

Bunun eski bir soru olduğunu biliyorum, ancak son zamanlarda uyguladığım ilginç bir örnek daha olduğunu düşünüyorum.

Bu, bir belge teslim sisteminde kullanılan strateji modelinin çok pratik bir örneğidir.

Çok sayıda belge ve bazı meta veriler içeren bir arşiv alan bir PDF dağıtım sistemim vardı. Meta verilere dayanarak belgeyi nereye koyacağına karar verdi; diyelim ki, verilere bağlı olarak, ben belgeyi depolayabilir A, Bveya Cdepolama sistemleri veya üçünün bir karışımını.

Farklı müşteriler bu sistemi kullanıyordu ve hata durumunda farklı geri alma / hata işleme gereksinimleri vardı: Biri teslimat sisteminin ilk hatada durmasını, tüm belgeleri önceden deposunda bırakmasını, ancak süreci durdurmasını ve başka hiçbir şey teslim etmemesini istedi. ; diğeri B, depolama sırasında hata olması durumunda geri alınmasını istedi C, ancak daha önce teslim edilmiş olanı bıraktı A. Üçüncü veya dördüncü birinin de farklı ihtiyaçları olacağını hayal etmek kolaydır.

Sorunu çözmek için, teslimat mantığını ve ayrıca tüm depolardan geri alma yöntemlerini içeren temel bir teslim sınıfı oluşturdum. Bu yöntemler aslında hata durumunda doğrudan dağıtım sistemi tarafından çağrılmaz. Bunun yerine sınıf, hata durumunda çağrılan bir "Geri Alma / Hata İşleme Stratejisi" sınıfını (sistemi kullanan müşteriye dayalı olarak) almak için Bağımlılık Ekleme kullanır ve bu strateji için uygunsa geri alma yöntemlerini çağırır.

Teslimat sınıfı, strateji sınıfına ne olduğunu (hangi belgelerin hangi depolara teslim edildiğini ve hangi başarısızlıkların gerçekleştiğini) rapor eder ve bir hata meydana geldiğinde stratejiye devam edip etmeyeceğini sorar. Strateji "durdur" diyorsa, sınıf stratejinin "cleanUp" yöntemini çağırır; bu yöntem, teslimat sınıfından hangi geri alma yöntemlerinin çağrılacağına karar vermek için önceden bildirilen bilgileri kullanır veya hiçbir şey yapmaz.

rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);

if (rollbackStrategy.mustAbort()) {
    rollbackStrategy.rollback(); // rollback whatever is needed based on reports
    return false;
}

Şimdi iki farklı stratejim var: biri QuitterStrategy(ilk hatadan çıkan ve hiçbir şeyi temizlemeyen) ve diğeri MaximizeDeliveryToAStrategy(mümkün olduğunca işlemi iptal etmemeye çalışan ve depoya teslim edilen şeyleri asla geri almamaya çalışan A, ancak Bteslimat Cbaşarısız olursa öğeleri geri alır ).

Benim anlayışıma göre, bu strateji modelinin bir örneğidir. Eğer (evet, okuyorsun) yanlış olduğumu düşünüyorsan, lütfen aşağıya yorum yap ve bana haber ver. Strateji modelinin "saf" kullanımını neyin oluşturacağını ve uygulamamın hangi yönlerinin tanımı ihlal ettiğini merak ediyorum. Strateji arayüzü biraz şişman olduğu için biraz komik göründüğünü düşünüyorum. Şimdiye kadar gördüğüm tüm örnekler yalnızca bir yöntem kullanıyor, ancak yine de bunun bir algoritmayı kapsadığını düşünüyorum (eğer bir iş mantığı parçası bir algoritma olarak kabul edilebilirse, ki öyle olduğunu düşünüyorum).

Strateji ayrıca teslimat uygulaması sırasında olaylar hakkında da bilgilendirildiğinden, bir Gözlemci olarak da düşünülebilir , ancak bu başka bir hikaye.

Küçük bir araştırma yapmaktan, bunun Danışman olarak adlandırılan bir "bileşik model" (MVC gibi, altında belirli bir şekilde birden fazla tasarım modeli kullanan bir model) olduğu anlaşılıyor . Bu, dağıtımın devam edip etmeyeceği konusunda bir danışmandır, ancak istendiğinde işleri geri alabildiğinden aynı zamanda etkin bir hata işleyicidir.

Her neyse, bu strateji modelinin kullanımlarının çok basit / aptalca olduğu hissine kapılmanıza neden olabilecek oldukça karmaşık bir örnek. Diğer kalıplarla birlikte kullanıldığında gerçekten karmaşık ve daha da uygulanabilir olabilir.


6

Strateji modeline iyi bir örnek, farklı karakterlere sahip olabileceğimiz ve her karakterin saldırmak için birden fazla silahı olabileceği ancak bir seferde yalnızca bir silah kullanabileceği bir oyunda olabilir. Dolayısıyla, bağlam olarak karakterimiz var, örneğin, saldırı () 'nın kullanılan silahlara bağlı bir yöntem / algoritma olabileceği bir strateji olarak Kral, Komutan, Şövalye, Asker ve silah. Yani eğer somut silah sınıfları Kılıç, Balta, Arbalet, BowAndArrow vb. Olsaydı, hepsi attack () yöntemini uygulardı. Daha fazla açıklamaya gerek olmadığından eminim.


1
Kabul edilen cevabın bu örnek hakkında konuşması gerektiğini düşündüm :)
Jeancarlo Fontalvo

6

Strateji modeli, özellikle doğrulamalar ve sıralama algoritmaları için en yaygın olarak kullanılan modeldir.

Basit bir pratik örnekle açıklamama izin verin

enum Speed {
  SLOW, MEDIUM, FAST;
}

class Sorter {
 public void sort(int[] input, Speed speed) {
    SortStrategy strategy = null;
    switch (speed) {
    case SLOW:
        strategy = new SlowBubbleSortStrategy();
        break;
    case MEDIUM:
        strategy = new MediumInsertationSortStrategy();
        break;

    case FAST:
        strategy = new FastQuickSortStrategy();
        break;
    default:
        strategy = new MediumInsertationSortStrategy();
    }
    strategy.sort(input);
 }

}

interface SortStrategy {

    public void sort(int[] input);
}

class SlowBubbleSortStrategy implements SortStrategy {

   public void sort(int[] input) {
    for (int i = 0; i < input.length; i++) {
        for (int j = i + 1; j < input.length; j++) {
            if (input[i] > input[j]) {
                int tmp = input[i];
                input[i] = input[j];
                input[j] = tmp;
            }
        }
    }
    System.out.println("Slow sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }
  }

 }

class MediumInsertationSortStrategy implements SortStrategy {

public void sort(int[] input) {
    for (int i = 0; i < input.length - 1; i++) {
        int k = i + 1;
        int nxtVal = input[k];
        while (input[k - 1] > nxtVal) {
            input[k] = input[k - 1];
            k--;
            if (k == 0)
                break;
        }
        input[k] = nxtVal;
    }
    System.out.println("Medium sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }

 }

}

class FastQuickSortStrategy implements SortStrategy {

public void sort(int[] input) {
    sort(input, 0, input.length-1);
    System.out.println("Fast sorting is done and the result is :");
    for (int i : input) {
        System.out.print(i + ",");
    }
}

private void sort(int[] input, int startIndx, int endIndx) {
    int endIndexOrig = endIndx;
    int startIndexOrig = startIndx;
    if( startIndx >= endIndx)
        return;
    int pavitVal = input[endIndx];
    while (startIndx <= endIndx) {
        while (input[startIndx] < pavitVal)
            startIndx++;
        while (input[endIndx] > pavitVal)
            endIndx--;
        if( startIndx <= endIndx){
            int tmp = input[startIndx];
            input[startIndx] = input[endIndx];
            input[endIndx] = tmp;
            startIndx++;
            endIndx--;
        }
    }
    sort(input, startIndexOrig, endIndx);
    sort(input, startIndx, endIndexOrig);
 }

}  

Bunun test kodu

public class StrategyPattern {
  public static void main(String[] args) {
    Sorter sorter = new Sorter();
    int[] input = new int[] {7,1,23,22,22,11,0,21,1,2,334,45,6,11,2};
    System.out.print("Input is : ");
    for (int i : input) {
        System.out.print(i + ",");
    }
    System.out.println();
    sorter.sort(input, Speed.SLOW);
 }

}

Aynı örnek http://coder2design.com/strategy-pattern/ adresinden alınmıştır.


Strateji modelinin farklı kullanımları: Doğrulamalar: Kodunuzda çok sayıda doğrulama yapılması gerektiğinde. Farklı Algoritmalar: Özellikle farklı sıralama algoritmaları kullanılabildiğinde, örneğin balonlu sıralama veya hızlı sıralama. Bilgilerin Saklanması: Veri tabanı veya dosya sistemi gibi farklı yerlerde bilgi alabildiğimizde. Ayrıştırma: Ayrıştırırken farklı girdiler için farklı stratejiler kullanabiliriz. Filtreleme Stratejileri. Yerleşim Stratejileri.
Jatinder Pal

2

İyi bir örnek olan bir uygulamada strateji yaklaşımını oldukça karmaşık bir motorda kullandım. Esasen, motorun rolü gidip önce bir parçacığı olan kişilerin bir listesini bulmaktı, ikinci rolü, bilinmeyen sayıda parametreye dayalı olarak bir parçacığa sahip en iyi 10 kişinin hangileri olduğunu bulmaktı , stok miktarı, nakliye seçenekleri vs vs ...)

Esasen yaptığımız şey, sorunu iki stratejiye ayırmaktı, ilki veri alma idi, çünkü widget'larımızın birden çok kaynağına sahip olduğumuzu biliyorduk ve verileri alıp ortak bir yapıya dönüştürebilmemiz gerekiyordu.

Daha sonra, bazılarının parametrelerin ağırlıklandırılmasına dayanan birden fazla algoritmamız olduğunu, diğerlerinin çok tuhaf ve propitery olduğunu ve vizolar ve çizelgeleri çıkarmadan onları adaletli yapamayacağımızı fark ettik ve iyi bir şekilde resmi elde ettiniz, için birçok algoritmamız vardı. en iyi insanları seçmek.

Hizmetimizin kendisi esasen girdileri, çıktıları tanımlayan ve verilerin bir miktar normalleştirilmesini sağlayan şeydi, ayrıca uygulamaya özel veri sağlayıcılarını ve stratejiyi kullanan algoritma sağlayıcılarını takmak için bir sağlayıcı modeli kullandı. Bu oldukça etkili bir sistemdi.

Asla çözemediğimiz bir strateji veya şablon kalıp kullanıp kullanmadığımız konusunda bazı tartışmalarımız oldu.


2

Bir "sipariş" durumunun bir Devlet modeli olmadığından emin misiniz? Bir siparişin durumuna bağlı olarak farklı şekilde ele alınmayacağına dair bir önsezim var.

Örneğin Siparişte Gönderme yöntemini ele alalım :

order.Ship();
  • Gönderim yöntemi durumuna göre değişiklik gösteriyorsa, bir strateji kalıbınız vardır.
  • Bununla birlikte, Ship () yöntemi yalnızca sipariş ödendiğinde başarılı olursa ve sipariş henüz gönderilmediyse, bir durum modeline sahipsiniz demektir.

Bulduğum durum örüntüsüne (ve diğer örüntülere) en iyi örnek , şaşırtıcı olan " Önce Baş Tasarım Kalıpları " kitabındaydı . Yakın bir saniye, David Cumps'in bloglama modelleri dizisi olacak .


2

Diyelim ki belirli bir ayın ve yılın n. Xgününü hesaplamak için bir algoritma yazmak istiyorsunuz , örneğin Ekim 2014'ün ikinci Pazartesi günü. android.text.format.TimeTarihi temsil etmek için Android'in Time sınıfını kullanmak istiyorsunuz , ancak aynı zamanda genel bir algoritma da yazmak istiyorsunuz bu da geçerli olabilir java.util.Calendar.

Ben öyle yaptım.

DatetimeMath.java'da:

public interface DatetimeMath { 
    public Object createDatetime(int year, int month, int day);

    public int getDayOfWeek(Object datetime);

    public void increment(Object datetime);
}

TimeMath.java'da:

public class TimeMath implements DatetimeMath {
    @Override
    public Object createDatetime(int year, int month, int day) {
        Time t = new Time();
        t.set(day, month, year);
        t.normalize(false);
        return t;
    }

    @Override
    public int getDayOfWeek(Object o) {
        Time t = (Time)o;
        return t.weekDay;
    }   

    @Override
    public void increment(Object o) {
        Time t = (Time)o;
        t.set(t.monthDay + 1, t.month, t.year);
        t.normalize(false);
    }
}

OrdinalDayOfWeekCalculator.java'da, genel algoritmaya sahip sınıf:

public class OrdinalDayOfWeekCalculator {   
    private DatetimeMath datetimeMath;

    public OrdinalDayOfWeekCalculator(DatetimeMath m) {
        datetimeMath = m;
    }

    public Object getDate(int year, int month, int dayOfWeek, int ordinal) {
        Object datetime = datetimeMath.createDatetime(year, month, 1);
        if (datetimeMath.getDayOfWeek(datetime) == dayOfWeek) {
            return datetime;
        } 
        int xDayCount = 0;
        while (xDayCount != ordinal) {
            datetimeMath.increment(datetime);
            if (datetimeMath.getDayOfWeek(datetime) == dayOfWeek) {
                xDayCount++;
            }
        }
        return datetime;
    }
}

Android uygulamamda şöyle bir şey çağırırdım

OrdinalDayOfWeekCalculator odowc = 
        new OrdinalDayOfWeekCalculator(new TimeMath());
Time canadianThanksgiving = (Time)odowc.getDate(
        year, Calendar.OCTOBER, Time.MONDAY, 2);

Aynı algoritmayı yeniden kullanmak istersem java.util.Calendar, DatetimeMath'teki üç yöntemi uygulayan bir sınıf CalendarMath yazar ve sonra şunu kullanırdım:

OrdinalDayOfWeekCalculator odowc2 = 
        new OrdinalDayOfWeekCalculator(new CalendarMath());
Calendar canadianThanksgivingCal = (Calendar)odowc2.getDate(
        year, Calendar.OCTOBER, Calendar.MONDAY, 2);

2
public class StrategyDemo {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("1234", 10);
        Item item2 = new Item("5678", 40);

        cart.addItem(item1);
        cart.addItem(item2);

        // pay by paypal
        cart.pay(new PaypalStrategy("myemail@example.com", "mypwd"));

        // pay by credit card
        cart.pay(new CreditCardStrategy("Pankaj Kumar", "1234567890123456", "786", "12/15"));
    }
}

interface PaymentStrategy {
    public void pay(int amount);
}

class CreditCardStrategy implements PaymentStrategy {

    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public CreditCardStrategy(String nm, String ccNum, String cvv, String expiryDate) {
        this.name = nm;
        this.cardNumber = ccNum;
        this.cvv = cvv;
        this.dateOfExpiry = expiryDate;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid with credit/debit card");
    }

}

class PaypalStrategy implements PaymentStrategy {

    private String emailId;
    private String password;

    public PaypalStrategy(String email, String pwd) {
        this.emailId = email;
        this.password = pwd;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using Paypal.");
    }

}

class Item {

    private String upcCode;
    private int price;

    public Item(String upc, int cost) {
        this.upcCode = upc;
        this.price = cost;
    }

    public String getUpcCode() {
        return upcCode;
    }

    public int getPrice() {
        return price;
    }

}

class ShoppingCart {

    // List of items
    List<Item> items;

    public ShoppingCart() {
        this.items = new ArrayList<Item>();
    }

    public void addItem(Item item) {
        this.items.add(item);
    }

    public void removeItem(Item item) {
        this.items.remove(item);
    }

    public int calculateTotal() {
        int sum = 0;
        for (Item item : items) {
            sum += item.getPrice();
        }
        return sum;
    }

    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}

1

Birkaç hafta önce, etki alanı nesnelerimizden biri tarafından uygulanan ortak bir Java arabirimi ekledim. Bu etki alanı nesnesi veritabanından yüklendi ve veritabanı temsili, yaklaşık 10+ dalı olan bir yıldız şemasıydı. Bu kadar ağır bir etki alanı nesnesine sahip olmanın sonuçlarından biri, aynı şemayı temsil eden, daha az ağır olsa da başka etki alanı nesneleri yapmak zorunda olmamızdır. Bu yüzden diğer hafif nesnelerin aynı arayüzü uygulamasını sağladım. Aksi takdirde biz vardı:

public interface CollectibleElephant { 
    long getId();
    String getName();
    long getTagId();
}

public class Elephant implements CollectibleElephant { ... }
public class BabyElephant implements CollectibleElephant { ... }

Başlangıçta CollectibleElephante'leri sıralamak için kullanmak istedim Elephant. Çok hızlı bir şekilde, ekip arkadaşlarım CollectibleElephantgüvenlik kontrolleri yapmak, GUI'ye gönderildikçe onları filtrelemek vb.


1

Çok karmaşık bir veritabanına sahip bir kurumsal platform için üçüncü taraf bir provizyon arayüzü oluşturmamız gerekiyordu. Sağlanacak verilerin gönderilmesi, uygulamamızda öncelik sırasına konan veri türlerimizin bir listesi olarak yapıldı, böylece bağımlılıklar nedeniyle veritabanına doğru sırada yazılabilirdi.

Bu verileri yazma işlemi o zaman oldukça basitti, öncelik sırasının en üstünden çıkmaya devam edin ve ardından çıkardığınız nesnenin türüne göre bir strateji seçin.


0

Wikipedia'dan

Bilgisayar programlamasında, strateji modeli (politika modeli olarak da bilinir), çalışma zamanında bir algoritma seçmeyi sağlayan davranışsal bir yazılım tasarım modelidir. Doğrudan tek bir algoritma uygulamak yerine, kod, bir algoritma ailesinde hangisinin kullanılacağına dair çalışma zamanı talimatlarını alır.

Windows Paint uygulamasında, şekli ve rengi bağımsız olarak farklı bölümlerde seçebileceğiniz bir strateji modeli görebilirsiniz. Burada şekil ve renk, çalışma zamanında değiştirilebilen algoritmalardır.

Bir 'RedCircle' seçeneği sunmak yerine kırmızı renkli bir daire çizmek istiyorsanız, daire ve istediğiniz rengi seçmenize izin verir.

Shape redCircle = new RedCircle(); // Without stretegy Pattern
Shaped redCircle = new Shape("red","circle"); // With Strategy pattern

Strateji olmadan desen, şekil ve renk Kartezyen ürünü ile sınıfların sayısını artıracaktır. Ayrıca arayüz her uygulama için değişir.


0

Örneğin, AI düşmanlarının olduğu bir nişancı oyunu hayal edin. Olanlara bağlı olarak sürekli farklı şekillerde savaşmalarını istiyorsunuz. Strateji modeli ile belirli bir eylemin veya eylemin nasıl gerçekleştirileceğini sürekli olarak döngüye sokabilir ve dinamik olarak değiştirebilirsiniz.

interface FightingStategy{
    public void fight();
}
public Defense implements FightingStrategy{
    public void figth(){
        ... hide behind wall to shoot
    }
}
public Berserker implements FightingStrategy{
    public void fight(){
        ... run towards you, headrolls and shoots
    }
}
public Dead implements FightingStrategy{
    public void fight(){
        ... is dead, doesn't move
    }
}

public AiShooter{

    FightingStrategy fightingStrategy;

    public AiShooter(){
        fightStrategy = new Berserker();
    }

    public void fight(){
        this.fightingStrategy.fight();
    }

    public void changeStrategy(FightingStrategy f){
        this.fightingStrategy = f;
    }
}

public static void main(){

    ... create list of AiShooters...
    while (condition){
        list.forEach(shooter -> shooter.fight());
    }
    ... you shoot back
    list.ForEach(shooter -> shooter.changeStrategy(new 
Defense()));

    ... you kill one
    list.get(n).changeStrategy(new Dead());
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.